summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/_updown/_updown.in10
-rw-r--r--src/charon-cmd/cmd/cmd_connection.c2
-rw-r--r--src/charon-tkm/src/tkm/tkm_encoder.c~106
-rw-r--r--src/charon-tkm/tests/tests.c4
-rw-r--r--src/conftest/actions.c2
-rw-r--r--src/include/Makefile.am3
-rw-r--r--src/include/Makefile.in3
-rw-r--r--src/include/linux/netlink.h212
-rw-r--r--src/include/linux/rtnetlink.h707
-rw-r--r--src/include/linux/types.h172
-rw-r--r--src/ipsec/_ipsec.82
-rw-r--r--src/libcharon/config/ike_cfg.c47
-rw-r--r--src/libcharon/config/ike_cfg.h17
-rw-r--r--src/libcharon/control/controller.c54
-rw-r--r--src/libcharon/control/controller.h5
-rw-r--r--src/libcharon/daemon.c4
-rw-r--r--src/libcharon/encoding/payloads/fragment_payload.c2
-rw-r--r--src/libcharon/encoding/payloads/proposal_substructure.c11
-rw-r--r--src/libcharon/network/receiver.c16
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius.c13
-rw-r--r--src/libcharon/plugins/eap_radius/eap_radius_accounting.c28
-rw-r--r--src/libcharon/plugins/eap_tnc/eap_tnc.c4
-rw-r--r--src/libcharon/plugins/eap_ttls/eap_ttls_peer.c9
-rw-r--r--src/libcharon/plugins/error_notify/error_notify_listener.c8
-rw-r--r--src/libcharon/plugins/ha/ha_ctl.c85
-rw-r--r--src/libcharon/plugins/ha/ha_dispatcher.c12
-rw-r--r--src/libcharon/plugins/ha/ha_ike.c1
-rw-r--r--src/libcharon/plugins/ha/ha_kernel.c21
-rw-r--r--src/libcharon/plugins/load_tester/load_tester.c1
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_control.c2
-rw-r--r--src/libcharon/plugins/load_tester/load_tester_plugin.c2
-rw-r--r--src/libcharon/plugins/medcli/medcli_config.c2
-rw-r--r--src/libcharon/plugins/osx_attr/osx_attr_handler.c30
-rw-r--r--src/libcharon/plugins/smp/smp.c2
-rw-r--r--src/libcharon/plugins/sql/sql_config.c11
-rw-r--r--src/libcharon/plugins/sql/sql_logger.c1
-rw-r--r--src/libcharon/plugins/stroke/stroke_ca.c238
-rw-r--r--src/libcharon/plugins/stroke/stroke_ca.h30
-rw-r--r--src/libcharon/plugins/stroke/stroke_config.c83
-rw-r--r--src/libcharon/plugins/stroke/stroke_control.c4
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.c257
-rw-r--r--src/libcharon/plugins/stroke/stroke_cred.h15
-rw-r--r--src/libcharon/plugins/stroke/stroke_list.c2
-rw-r--r--src/libcharon/plugins/stroke/stroke_socket.c4
-rw-r--r--src/libcharon/plugins/tnc_ifmap/tnc_ifmap_renew_session_job.h2
-rw-r--r--src/libcharon/plugins/uci/uci_control.c2
-rw-r--r--src/libcharon/plugins/updown/updown_listener.c18
-rw-r--r--src/libcharon/plugins/vici/Makefile.am1
-rw-r--r--src/libcharon/plugins/vici/Makefile.in4
-rw-r--r--src/libcharon/plugins/vici/README.md124
-rw-r--r--src/libcharon/plugins/vici/python/LICENSE2
-rw-r--r--src/libcharon/plugins/vici/python/vici/exception.py3
-rw-r--r--src/libcharon/plugins/vici/python/vici/session.py138
-rw-r--r--src/libcharon/plugins/vici/ruby/lib/vici.rb6
-rw-r--r--src/libcharon/plugins/vici/suites/test_message.c31
-rw-r--r--src/libcharon/plugins/vici/vici_authority.c750
-rw-r--r--src/libcharon/plugins/vici/vici_authority.h62
-rw-r--r--src/libcharon/plugins/vici/vici_config.c67
-rw-r--r--src/libcharon/plugins/vici/vici_config.h8
-rw-r--r--src/libcharon/plugins/vici/vici_control.c11
-rw-r--r--src/libcharon/plugins/vici/vici_cred.c7
-rw-r--r--src/libcharon/plugins/vici/vici_cred.h8
-rw-r--r--src/libcharon/plugins/vici/vici_logger.c48
-rw-r--r--src/libcharon/plugins/vici/vici_message.c40
-rw-r--r--src/libcharon/plugins/vici/vici_message.h25
-rw-r--r--src/libcharon/plugins/vici/vici_plugin.c16
-rw-r--r--src/libcharon/plugins/vici/vici_query.c87
-rw-r--r--src/libcharon/plugins/whitelist/whitelist_listener.c2
-rw-r--r--src/libcharon/processing/jobs/initiate_mediation_job.c4
-rw-r--r--src/libcharon/processing/jobs/process_message_job.c14
-rw-r--r--src/libcharon/processing/jobs/rekey_child_sa_job.c5
-rw-r--r--src/libcharon/processing/jobs/start_action_job.c2
-rw-r--r--src/libcharon/sa/child_sa.c15
-rw-r--r--src/libcharon/sa/eap/eap_method.c3
-rw-r--r--src/libcharon/sa/ike_sa.c43
-rw-r--r--src/libcharon/sa/ike_sa_id.c4
-rw-r--r--src/libcharon/sa/ike_sa_manager.c67
-rw-r--r--src/libcharon/sa/ike_sa_manager.h9
-rw-r--r--src/libcharon/sa/ikev1/phase1.c2
-rw-r--r--src/libcharon/sa/ikev1/task_manager_v1.c35
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.c26
-rw-r--r--src/libcharon/sa/ikev1/tasks/quick_mode.h11
-rw-r--r--src/libcharon/sa/ikev2/authenticators/eap_authenticator.c9
-rw-r--r--src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c2
-rw-r--r--src/libcharon/sa/ikev2/keymat_v2.c2
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_create.c36
-rw-r--r--src/libcharon/sa/ikev2/tasks/child_rekey.c18
-rw-r--r--src/libcharon/sa/ikev2/tasks/ike_rekey.c34
-rw-r--r--src/libcharon/sa/shunt_manager.c71
-rw-r--r--src/libcharon/sa/shunt_manager.h6
-rw-r--r--src/libcharon/sa/trap_manager.c276
-rw-r--r--src/libcharon/tests/Makefile.am4
-rw-r--r--src/libcharon/tests/Makefile.in40
-rw-r--r--src/libcharon/tests/libcharon_tests.c18
-rw-r--r--src/libcharon/tests/libcharon_tests.h2
-rw-r--r--src/libcharon/tests/suites/test_ike_cfg.c118
-rw-r--r--src/libcharon/tests/suites/test_message_chapoly.c138
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c53
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c40
-rw-r--r--src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c16
-rw-r--r--src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c118
-rw-r--r--src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c17
-rw-r--r--src/libhydra/tests/hydra_tests.c4
-rw-r--r--src/libimcv/Android.mk7
-rw-r--r--src/libimcv/Makefile.am15
-rw-r--r--src/libimcv/Makefile.in74
-rw-r--r--src/libimcv/generic/generic_attr_bool.c (renamed from src/libimcv/ietf/ietf_attr_default_pwd_enabled.c)80
-rw-r--r--src/libimcv/generic/generic_attr_bool.h67
-rw-r--r--src/libimcv/generic/generic_attr_chunk.c (renamed from src/libimcv/ita/ita_attr_device_id.c)65
-rw-r--r--src/libimcv/generic/generic_attr_chunk.h60
-rw-r--r--src/libimcv/generic/generic_attr_string.c183
-rw-r--r--src/libimcv/generic/generic_attr_string.h (renamed from src/libimcv/ita/ita_attr_device_id.h)35
-rw-r--r--src/libimcv/ietf/ietf_attr.c13
-rw-r--r--src/libimcv/ietf/ietf_attr_default_pwd_enabled.h65
-rw-r--r--src/libimcv/ietf/ietf_attr_fwd_enabled.c11
-rw-r--r--src/libimcv/ietf/ietf_attr_fwd_enabled.h9
-rw-r--r--src/libimcv/ietf/ietf_attr_port_filter.c10
-rw-r--r--src/libimcv/ietf/ietf_attr_port_filter.h8
-rw-r--r--src/libimcv/imc/imc_msg.c30
-rw-r--r--src/libimcv/imc/imc_os_info.c11
-rw-r--r--src/libimcv/imc/imc_os_info.h9
-rw-r--r--src/libimcv/imcv.c7
-rw-r--r--src/libimcv/imcv.h3
-rw-r--r--src/libimcv/imv/imv_msg.c28
-rw-r--r--src/libimcv/ita/ita_attr.c5
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_msg.c10
-rw-r--r--src/libimcv/pa_tnc/pa_tnc_msg.h9
-rw-r--r--src/libimcv/plugins/imc_hcd/Makefile.am16
-rw-r--r--src/libimcv/plugins/imc_hcd/Makefile.in763
-rw-r--r--src/libimcv/plugins/imc_hcd/imc_hcd.c791
-rw-r--r--src/libimcv/plugins/imc_hcd/imc_hcd_state.c176
-rw-r--r--src/libimcv/plugins/imc_hcd/imc_hcd_state.h50
-rw-r--r--src/libimcv/plugins/imc_os/imc_os.c24
-rw-r--r--src/libimcv/plugins/imc_scanner/imc_scanner.c7
-rw-r--r--src/libimcv/plugins/imc_swid/imc_swid.c6
-rw-r--r--src/libimcv/plugins/imv_attestation/imv_attestation_agent.c8
-rw-r--r--src/libimcv/plugins/imv_hcd/Makefile.am18
-rw-r--r--src/libimcv/plugins/imv_hcd/Makefile.in767
-rw-r--r--src/libimcv/plugins/imv_hcd/imv_hcd.c24
-rw-r--r--src/libimcv/plugins/imv_hcd/imv_hcd_agent.c680
-rw-r--r--src/libimcv/plugins/imv_hcd/imv_hcd_agent.h36
-rw-r--r--src/libimcv/plugins/imv_hcd/imv_hcd_state.c350
-rw-r--r--src/libimcv/plugins/imv_hcd/imv_hcd_state.h120
-rw-r--r--src/libimcv/plugins/imv_os/imv_os_agent.c19
-rw-r--r--src/libimcv/plugins/imv_os/pacman.c21
-rw-r--r--src/libimcv/plugins/imv_scanner/imv_scanner_agent.c4
-rw-r--r--src/libimcv/plugins/imv_swid/imv_swid_agent.c6
-rw-r--r--src/libimcv/pwg/pwg_attr.c123
-rw-r--r--src/libimcv/pwg/pwg_attr.h75
-rw-r--r--src/libimcv/pwg/pwg_attr_vendor_smi_code.c236
-rw-r--r--src/libimcv/pwg/pwg_attr_vendor_smi_code.h65
-rw-r--r--src/libimcv/seg/seg_contract.c6
-rw-r--r--src/libimcv/seg/seg_contract.h6
-rw-r--r--src/libimcv/seg/seg_env.c15
-rw-r--r--src/libimcv/seg/seg_env.h5
-rw-r--r--src/libimcv/suites/test_imcv_seg.c15
-rw-r--r--src/libipsec/Makefile.am9
-rw-r--r--src/libipsec/Makefile.in8
-rw-r--r--src/libipsec/esp_context.c1
-rw-r--r--src/libipsec/tests/Makefile.am21
-rw-r--r--src/libipsec/tests/Makefile.in870
-rw-r--r--src/libipsec/tests/ipsec_tests.c57
-rw-r--r--src/libipsec/tests/ipsec_tests.h16
-rw-r--r--src/libipsec/tests/suites/test_chapoly.c136
-rw-r--r--src/libpttls/pt_tls_client.c1
-rw-r--r--src/libradius/radius_message.c9
-rw-r--r--src/libradius/radius_message.h5
-rw-r--r--src/libstrongswan/Makefile.am9
-rw-r--r--src/libstrongswan/Makefile.in65
-rw-r--r--src/libstrongswan/asn1/asn1.c2
-rw-r--r--src/libstrongswan/credentials/auth_cfg.c39
-rw-r--r--src/libstrongswan/credentials/certificates/ocsp_request.h2
-rw-r--r--src/libstrongswan/credentials/certificates/ocsp_response.h2
-rw-r--r--src/libstrongswan/credentials/sets/mem_cred.c58
-rw-r--r--src/libstrongswan/credentials/sets/mem_cred.h12
-rw-r--r--src/libstrongswan/crypto/crypters/crypter.c8
-rw-r--r--src/libstrongswan/crypto/crypters/crypter.h1
-rw-r--r--src/libstrongswan/crypto/iv/iv_gen.c1
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords_static.c295
-rw-r--r--src/libstrongswan/crypto/proposal/proposal_keywords_static.txt1
-rw-r--r--src/libstrongswan/networking/host.c4
-rw-r--r--src/libstrongswan/pen/pen.c6
-rw-r--r--src/libstrongswan/pen/pen.h3
-rw-r--r--src/libstrongswan/plugins/bliss/bliss_private_key.c18
-rw-r--r--src/libstrongswan/plugins/bliss/bliss_public_key.c19
-rw-r--r--src/libstrongswan/plugins/bliss/bliss_utils.c83
-rw-r--r--src/libstrongswan/plugins/bliss/bliss_utils.h10
-rw-r--r--src/libstrongswan/plugins/chapoly/Makefile.am29
-rw-r--r--src/libstrongswan/plugins/chapoly/Makefile.in810
-rw-r--r--src/libstrongswan/plugins/chapoly/chapoly_aead.c333
-rw-r--r--src/libstrongswan/plugins/chapoly/chapoly_aead.h52
-rw-r--r--src/libstrongswan/plugins/chapoly/chapoly_drv.c43
-rw-r--r--src/libstrongswan/plugins/chapoly/chapoly_drv.h113
-rw-r--r--src/libstrongswan/plugins/chapoly/chapoly_drv_portable.c454
-rw-r--r--src/libstrongswan/plugins/chapoly/chapoly_drv_portable.h31
-rw-r--r--src/libstrongswan/plugins/chapoly/chapoly_drv_ssse3.c867
-rw-r--r--src/libstrongswan/plugins/chapoly/chapoly_drv_ssse3.h31
-rw-r--r--src/libstrongswan/plugins/chapoly/chapoly_plugin.c75
-rw-r--r--src/libstrongswan/plugins/chapoly/chapoly_plugin.h42
-rw-r--r--src/libstrongswan/plugins/des/des_crypter.c2
-rw-r--r--src/libstrongswan/plugins/padlock/padlock_sha1_hasher.h2
-rw-r--r--src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c11
-rw-r--r--src/libstrongswan/plugins/plugin_feature.c18
-rw-r--r--src/libstrongswan/plugins/plugin_feature.h10
-rw-r--r--src/libstrongswan/plugins/test_vectors/Makefile.am1
-rw-r--r--src/libstrongswan/plugins/test_vectors/Makefile.in14
-rw-r--r--src/libstrongswan/plugins/test_vectors/test_vectors.h4
-rw-r--r--src/libstrongswan/plugins/test_vectors/test_vectors/chacha20poly1305.c107
-rw-r--r--src/libstrongswan/selectors/traffic_selector.c3
-rw-r--r--src/libstrongswan/settings/settings.c69
-rw-r--r--src/libstrongswan/settings/settings.h54
-rw-r--r--src/libstrongswan/settings/settings_lexer.c233
-rw-r--r--src/libstrongswan/settings/settings_lexer.l19
-rw-r--r--src/libstrongswan/settings/settings_parser.c171
-rw-r--r--src/libstrongswan/settings/settings_parser.h8
-rw-r--r--src/libstrongswan/settings/settings_parser.y39
-rw-r--r--src/libstrongswan/tests/suites/test_chunk.c2
-rw-r--r--src/libstrongswan/tests/suites/test_host.c6
-rw-r--r--src/libstrongswan/tests/suites/test_identification.c91
-rw-r--r--src/libstrongswan/tests/suites/test_settings.c172
-rw-r--r--src/libstrongswan/tests/suites/test_traffic_selector.c594
-rw-r--r--src/libstrongswan/tests/test_runner.c2
-rw-r--r--src/libstrongswan/tests/test_suite.c2
-rw-r--r--src/libstrongswan/tests/tests.c4
-rw-r--r--src/libstrongswan/utils/capabilities.c60
-rw-r--r--src/libstrongswan/utils/identification.c48
-rw-r--r--src/libstrongswan/utils/identification.h15
-rw-r--r--src/libstrongswan/utils/printf_hook/printf_hook_builtin.c3
-rw-r--r--src/libstrongswan/utils/printf_hook/printf_hook_builtin.h2
-rw-r--r--src/libstrongswan/utils/printf_hook/printf_hook_vstr.h2
-rw-r--r--src/libstrongswan/utils/utils.c107
-rw-r--r--src/libstrongswan/utils/utils/string.c2
-rw-r--r--src/libtls/tests/tls_tests.c4
-rw-r--r--src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c8
-rw-r--r--src/libtncif/tncif_pa_subtypes.c57
-rw-r--r--src/libtncif/tncif_pa_subtypes.h31
-rw-r--r--src/pki/Makefile.am9
-rw-r--r--src/pki/Makefile.in39
-rw-r--r--src/pki/command.h2
-rw-r--r--src/pki/commands/dn.c146
-rw-r--r--src/pki/commands/issue.c35
-rw-r--r--src/pki/man/Makefile.am11
-rw-r--r--src/pki/man/Makefile.in37
-rw-r--r--src/pki/man/pki---dn.1.in56
-rw-r--r--src/pki/man/pki---issue.1.in5
-rw-r--r--src/pki/man/pki.1.in6
-rw-r--r--src/starter/netkey.c13
-rw-r--r--src/starter/netkey.h1
-rw-r--r--src/starter/parser/conf_parser.h2
-rw-r--r--src/starter/parser/lexer.c266
-rw-r--r--src/starter/parser/lexer.l11
-rw-r--r--src/starter/parser/parser.c62
-rw-r--r--src/starter/parser/parser.h6
-rw-r--r--src/starter/parser/parser.y2
-rw-r--r--src/starter/starter.c1
-rw-r--r--src/starter/starterstroke.c1
-rw-r--r--src/starter/tests/suites/test_parser.c3
-rw-r--r--src/stroke/stroke.c1
-rw-r--r--src/swanctl/Makefile.am4
-rw-r--r--src/swanctl/Makefile.in12
-rw-r--r--src/swanctl/command.c2
-rw-r--r--src/swanctl/command.h2
-rw-r--r--src/swanctl/commands/list_authorities.c169
-rw-r--r--src/swanctl/commands/list_certs.c5
-rw-r--r--src/swanctl/commands/load_all.c8
-rw-r--r--src/swanctl/commands/load_authorities.c365
-rw-r--r--src/swanctl/commands/load_authorities.h26
-rw-r--r--src/swanctl/swanctl.8.in8
-rw-r--r--src/swanctl/swanctl.conf25
-rw-r--r--src/swanctl/swanctl.conf.5.main37
-rw-r--r--src/swanctl/swanctl.opt38
271 files changed, 15589 insertions, 2669 deletions
diff --git a/src/_updown/_updown.in b/src/_updown/_updown.in
index 4090fe074..6e7abca09 100644
--- a/src/_updown/_updown.in
+++ b/src/_updown/_updown.in
@@ -71,7 +71,7 @@
# PLUTO_MY_SOURCEIP6_$i
# contains IPv4/IPv6 virtual IP received from a responder,
# $i enumerates from 1 to the number of IP per address family.
-# PLUTO_MY_SOURCEIP is a legacy variable and equals to the first
+# PLUTO_MY_SOURCEIP is a legacy variable and equal to the first
# virtual IP, IPv4 or IPv6.
#
# PLUTO_MY_PROTOCOL
@@ -94,6 +94,14 @@
# the peer's own IP address / max (where max is 32
# for IPv4 and 128 for IPv6).
#
+# PLUTO_PEER_SOURCEIP
+# PLUTO_PEER_SOURCEIP4_$i
+# PLUTO_PEER_SOURCEIP6_$i
+# contains IPv4/IPv6 virtual IP sent to an initiator,
+# $i enumerates from 1 to the number of IP per address family.
+# PLUTO_PEER_SOURCEIP is a legacy variable and equal to the first
+# virtual IP, IPv4 or IPv6.
+#
# PLUTO_PEER_PROTOCOL
# is the IP protocol that will be transported.
#
diff --git a/src/charon-cmd/cmd/cmd_connection.c b/src/charon-cmd/cmd/cmd_connection.c
index 2c0b7b9d5..0c6a504e9 100644
--- a/src/charon-cmd/cmd/cmd_connection.c
+++ b/src/charon-cmd/cmd/cmd_connection.c
@@ -434,7 +434,7 @@ static job_requeue_t initiate(private_cmd_connection_t *this)
child_cfg = create_child_cfg(this, peer_cfg);
if (charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
- controller_cb_empty, NULL, 0) != SUCCESS)
+ controller_cb_empty, NULL, 0, FALSE) != SUCCESS)
{
terminate(pid);
}
diff --git a/src/charon-tkm/src/tkm/tkm_encoder.c~ b/src/charon-tkm/src/tkm/tkm_encoder.c~
deleted file mode 100644
index 145615f14..000000000
--- a/src/charon-tkm/src/tkm/tkm_encoder.c~
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2013 Reto Buerki
- * Copyright (C) 2013 Adrian-Ken Rueegsegger
- * 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 <utils/debug.h>
-#include <asn1/asn1.h>
-#include <asn1/oid.h>
-
-#include "tkm_encoder.h"
-
-/**
- * Build the SHA1 hash of pubkey(info) ASN.1 data.
- */
-static bool hash_pubkey(chunk_t pubkey, chunk_t *hash)
-{
- hasher_t *hasher;
-
- hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
- if (!hasher || !hasher->allocate_hash(hasher, pubkey, hash))
- {
- DBG1(DBG_LIB, "SHA1 hash algorithm not supported, "
- "fingerprinting failed");
- DESTROY_IF(hasher);
- chunk_free(&pubkey);
- return FALSE;
- }
- hasher->destroy(hasher);
- chunk_free(&pubkey);
- return TRUE;
-}
-
-/**
- * Encode the public key blob into subjectPublicKeyInfo.
- */
-static bool build_pub_info(chunk_t *encoding, va_list args)
-{
- chunk_t blob;
-
- if (cred_encoding_args(args, CRED_PART_RSA_PUB_ASN1_DER, &blob,
- CRED_PART_END))
- {
- *encoding = asn1_wrap(ASN1_SEQUENCE, "mm",
- asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
- asn1_bitstring("c", blob, 0));
- return TRUE;
- }
- return FALSE;
-}
-
-/**
- * Build the fingerprint of the subjectPublicKeyInfo object.
- */
-static bool build_info_sha1(chunk_t *encoding, va_list args)
-{
- chunk_t pubkey;
-
- if (build_pub_info(&pubkey, args))
- {
- return hash_pubkey(pubkey, encoding);
- }
- return FALSE;
-}
-
-/**
- * Build the fingerprint of the subjectPublicKey object.
- */
-static bool build_sha1(chunk_t *encoding, va_list args)
-{
- chunk_t blob;
-
- if (cred_encoding_args(args, CRED_PART_RSA_PUB_ASN1_DER, &blob,
- CRED_PART_END))
- {
- return hash_pubkey(chunk_clone(blob), encoding);
- }
- return FALSE;
-}
-
-/**
- * See header.
- */
-bool tkm_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
- va_list args)
-{
- switch (type)
- {
- case KEYID_PUBKEY_INFO_SHA1:
- return build_info_sha1(encoding, args);
- case KEYID_PUBKEY_SHA1:
- return build_sha1(encoding, args);
- default:
- return FALSE;
- }
-}
diff --git a/src/charon-tkm/tests/tests.c b/src/charon-tkm/tests/tests.c
index 669f4d500..ac152b690 100644
--- a/src/charon-tkm/tests/tests.c
+++ b/src/charon-tkm/tests/tests.c
@@ -36,8 +36,8 @@
static test_configuration_t tests[] = {
#define TEST_SUITE(x) \
{ .suite = x, },
-#define TEST_SUITE_DEPEND(x, type, args) \
- { .suite = x, .feature = PLUGIN_DEPENDS(type, args) },
+#define TEST_SUITE_DEPEND(x, type, ...) \
+ { .suite = x, .feature = PLUGIN_DEPENDS(type, __VA_ARGS__) },
#include "tests.h"
{ .suite = NULL, }
};
diff --git a/src/conftest/actions.c b/src/conftest/actions.c
index 474672ca1..256b63d1b 100644
--- a/src/conftest/actions.c
+++ b/src/conftest/actions.c
@@ -65,7 +65,7 @@ static job_requeue_t initiate(char *config)
{
DBG1(DBG_CFG, "initiating IKE_SA for CHILD_SA config '%s'", config);
charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
- NULL, NULL, 0);
+ NULL, NULL, 0, FALSE);
}
else
{
diff --git a/src/include/Makefile.am b/src/include/Makefile.am
index 5de713143..0284c094a 100644
--- a/src/include/Makefile.am
+++ b/src/include/Makefile.am
@@ -1,3 +1,2 @@
EXTRA_DIST = linux/if_alg.h linux/ipsec.h linux/netlink.h linux/rtnetlink.h \
- linux/pfkeyv2.h linux/udp.h linux/xfrm.h linux/types.h \
- sys/queue.h
+ linux/pfkeyv2.h linux/udp.h linux/xfrm.h sys/queue.h
diff --git a/src/include/Makefile.in b/src/include/Makefile.in
index 64be6ac4f..e2c3cd0c3 100644
--- a/src/include/Makefile.in
+++ b/src/include/Makefile.in
@@ -343,8 +343,7 @@ urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
EXTRA_DIST = linux/if_alg.h linux/ipsec.h linux/netlink.h linux/rtnetlink.h \
- linux/pfkeyv2.h linux/udp.h linux/xfrm.h linux/types.h \
- sys/queue.h
+ linux/pfkeyv2.h linux/udp.h linux/xfrm.h sys/queue.h
all: all-am
diff --git a/src/include/linux/netlink.h b/src/include/linux/netlink.h
index 1aeee628b..777a1b7da 100644
--- a/src/include/linux/netlink.h
+++ b/src/include/linux/netlink.h
@@ -1,14 +1,15 @@
-#ifndef __LINUX_NETLINK_H
-#define __LINUX_NETLINK_H
+#ifndef _UAPI__LINUX_NETLINK_H
+#define _UAPI__LINUX_NETLINK_H
-#include <linux/socket.h> /* for sa_family_t */
+#include <linux/kernel.h>
+#include <linux/socket.h> /* for __kernel_sa_family_t */
#include <linux/types.h>
#define NETLINK_ROUTE 0 /* Routing/device hook */
-#define NETLINK_W1 1 /* 1-wire subsystem */
+#define NETLINK_UNUSED 1 /* Unused number */
#define NETLINK_USERSOCK 2 /* Reserved for user mode socket protocols */
-#define NETLINK_FIREWALL 3 /* Firewalling hook */
-#define NETLINK_INET_DIAG 4 /* INET socket monitoring */
+#define NETLINK_FIREWALL 3 /* Unused number, formerly ip_queue */
+#define NETLINK_SOCK_DIAG 4 /* socket monitoring */
#define NETLINK_NFLOG 5 /* netfilter/iptables ULOG */
#define NETLINK_XFRM 6 /* ipsec */
#define NETLINK_SELINUX 7 /* SELinux event notifications */
@@ -21,24 +22,29 @@
#define NETLINK_DNRTMSG 14 /* DECnet routing messages */
#define NETLINK_KOBJECT_UEVENT 15 /* Kernel messages to userspace */
#define NETLINK_GENERIC 16
+/* leave room for NETLINK_DM (DM Events) */
+#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
+#define NETLINK_ECRYPTFS 19
+#define NETLINK_RDMA 20
+#define NETLINK_CRYPTO 21 /* Crypto layer */
+
+#define NETLINK_INET_DIAG NETLINK_SOCK_DIAG
#define MAX_LINKS 32
-struct sockaddr_nl
-{
- sa_family_t nl_family; /* AF_NETLINK */
+struct sockaddr_nl {
+ __kernel_sa_family_t nl_family; /* AF_NETLINK */
unsigned short nl_pad; /* zero */
- __u32 nl_pid; /* process pid */
+ __u32 nl_pid; /* port ID */
__u32 nl_groups; /* multicast groups mask */
};
-struct nlmsghdr
-{
+struct nlmsghdr {
__u32 nlmsg_len; /* Length of message including header */
__u16 nlmsg_type; /* Message content */
__u16 nlmsg_flags; /* Additional flags */
__u32 nlmsg_seq; /* Sequence number */
- __u32 nlmsg_pid; /* Sending process PID */
+ __u32 nlmsg_pid; /* Sending process port ID */
};
/* Flags values */
@@ -47,6 +53,7 @@ struct nlmsghdr
#define NLM_F_MULTI 2 /* Multipart message, terminated by NLMSG_DONE */
#define NLM_F_ACK 4 /* Reply with ack, with zero or error code */
#define NLM_F_ECHO 8 /* Echo this request */
+#define NLM_F_DUMP_INTR 16 /* Dump was inconsistent due to sequence change */
/* Modifiers to GET request */
#define NLM_F_ROOT 0x100 /* specify tree root */
@@ -69,10 +76,10 @@ struct nlmsghdr
Check NLM_F_EXCL
*/
-#define NLMSG_ALIGNTO 4
+#define NLMSG_ALIGNTO 4U
#define NLMSG_ALIGN(len) ( ((len)+NLMSG_ALIGNTO-1) & ~(NLMSG_ALIGNTO-1) )
#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr)))
-#define NLMSG_LENGTH(len) ((len)+NLMSG_ALIGN(NLMSG_HDRLEN))
+#define NLMSG_LENGTH(len) ((len) + NLMSG_HDRLEN)
#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len))
#define NLMSG_DATA(nlh) ((void*)(((char*)nlh) + NLMSG_LENGTH(0)))
#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \
@@ -89,21 +96,54 @@ struct nlmsghdr
#define NLMSG_MIN_TYPE 0x10 /* < 0x10: reserved control messages */
-struct nlmsgerr
-{
+struct nlmsgerr {
int error;
struct nlmsghdr msg;
};
-#define NETLINK_ADD_MEMBERSHIP 1
-#define NETLINK_DROP_MEMBERSHIP 2
-#define NETLINK_PKTINFO 3
-
-struct nl_pktinfo
-{
+#define NETLINK_ADD_MEMBERSHIP 1
+#define NETLINK_DROP_MEMBERSHIP 2
+#define NETLINK_PKTINFO 3
+#define NETLINK_BROADCAST_ERROR 4
+#define NETLINK_NO_ENOBUFS 5
+#define NETLINK_RX_RING 6
+#define NETLINK_TX_RING 7
+#define NETLINK_LISTEN_ALL_NSID 8
+#define NETLINK_LIST_MEMBERSHIPS 9
+
+struct nl_pktinfo {
__u32 group;
};
+struct nl_mmap_req {
+ unsigned int nm_block_size;
+ unsigned int nm_block_nr;
+ unsigned int nm_frame_size;
+ unsigned int nm_frame_nr;
+};
+
+struct nl_mmap_hdr {
+ unsigned int nm_status;
+ unsigned int nm_len;
+ __u32 nm_group;
+ /* credentials */
+ __u32 nm_pid;
+ __u32 nm_uid;
+ __u32 nm_gid;
+};
+
+enum nl_mmap_status {
+ NL_MMAP_STATUS_UNUSED,
+ NL_MMAP_STATUS_RESERVED,
+ NL_MMAP_STATUS_VALID,
+ NL_MMAP_STATUS_COPY,
+ NL_MMAP_STATUS_SKIP,
+};
+
+#define NL_MMAP_MSG_ALIGNMENT NLMSG_ALIGNTO
+#define NL_MMAP_MSG_ALIGN(sz) __ALIGN_KERNEL(sz, NL_MMAP_MSG_ALIGNMENT)
+#define NL_MMAP_HDRLEN NL_MMAP_MSG_ALIGN(sizeof(struct nl_mmap_hdr))
+
#define NET_MAJOR 36 /* Major 36 is reserved for networking */
enum {
@@ -120,122 +160,28 @@ enum {
* <-------------- nlattr->nla_len -------------->
*/
-struct nlattr
-{
+struct nlattr {
__u16 nla_len;
__u16 nla_type;
};
-#define NLA_ALIGNTO 4
-#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
-#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
-
-#ifdef __KERNEL__
-
-#include <linux/capability.h>
-#include <linux/skbuff.h>
-
-struct netlink_skb_parms
-{
- struct ucred creds; /* Skb credentials */
- __u32 pid;
- __u32 dst_pid;
- __u32 dst_group;
- kernel_cap_t eff_cap;
- __u32 loginuid; /* Login (audit) uid */
- __u32 sid; /* SELinux security id */
-};
-
-#define NETLINK_CB(skb) (*(struct netlink_skb_parms*)&((skb)->cb))
-#define NETLINK_CREDS(skb) (&NETLINK_CB((skb)).creds)
-
-
-extern struct sock *netlink_kernel_create(int unit, unsigned int groups, void (*input)(struct sock *sk, int len), struct module *module);
-extern void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err);
-extern int netlink_has_listeners(struct sock *sk, unsigned int group);
-extern int netlink_unicast(struct sock *ssk, struct sk_buff *skb, __u32 pid, int nonblock);
-extern int netlink_broadcast(struct sock *ssk, struct sk_buff *skb, __u32 pid,
- __u32 group, gfp_t allocation);
-extern void netlink_set_err(struct sock *ssk, __u32 pid, __u32 group, int code);
-extern int netlink_register_notifier(struct notifier_block *nb);
-extern int netlink_unregister_notifier(struct notifier_block *nb);
-
-/* finegrained unicast helpers: */
-struct sock *netlink_getsockbyfilp(struct file *filp);
-int netlink_attachskb(struct sock *sk, struct sk_buff *skb, int nonblock,
- long timeo, struct sock *ssk);
-void netlink_detachskb(struct sock *sk, struct sk_buff *skb);
-int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol);
-
/*
- * skb should fit one page. This choice is good for headerless malloc.
+ * nla_type (16 bits)
+ * +---+---+-------------------------------+
+ * | N | O | Attribute Type |
+ * +---+---+-------------------------------+
+ * N := Carries nested attributes
+ * O := Payload stored in network byte order
+ *
+ * Note: The N and O flag are mutually exclusive.
*/
-#define NLMSG_GOODORDER 0
-#define NLMSG_GOODSIZE (SKB_MAX_ORDER(0, NLMSG_GOODORDER))
-
-
-struct netlink_callback
-{
- struct sk_buff *skb;
- struct nlmsghdr *nlh;
- int (*dump)(struct sk_buff * skb, struct netlink_callback *cb);
- int (*done)(struct netlink_callback *cb);
- int family;
- long args[5];
-};
-
-struct netlink_notify
-{
- int pid;
- int protocol;
-};
-
-static __inline__ struct nlmsghdr *
-__nlmsg_put(struct sk_buff *skb, __u32 pid, __u32 seq, int type, int len, int flags)
-{
- struct nlmsghdr *nlh;
- int size = NLMSG_LENGTH(len);
-
- nlh = (struct nlmsghdr*)skb_put(skb, NLMSG_ALIGN(size));
- nlh->nlmsg_type = type;
- nlh->nlmsg_len = size;
- nlh->nlmsg_flags = flags;
- nlh->nlmsg_pid = pid;
- nlh->nlmsg_seq = seq;
- memset(NLMSG_DATA(nlh) + len, 0, NLMSG_ALIGN(size) - size);
- return nlh;
-}
-
-#define NLMSG_NEW(skb, pid, seq, type, len, flags) \
-({ if (skb_tailroom(skb) < (int)NLMSG_SPACE(len)) \
- goto nlmsg_failure; \
- __nlmsg_put(skb, pid, seq, type, len, flags); })
+#define NLA_F_NESTED (1 << 15)
+#define NLA_F_NET_BYTEORDER (1 << 14)
+#define NLA_TYPE_MASK ~(NLA_F_NESTED | NLA_F_NET_BYTEORDER)
-#define NLMSG_PUT(skb, pid, seq, type, len) \
- NLMSG_NEW(skb, pid, seq, type, len, 0)
-
-#define NLMSG_NEW_ANSWER(skb, cb, type, len, flags) \
- NLMSG_NEW(skb, NETLINK_CB((cb)->skb).pid, \
- (cb)->nlh->nlmsg_seq, type, len, flags)
-
-#define NLMSG_END(skb, nlh) \
-({ (nlh)->nlmsg_len = (skb)->tail - (unsigned char *) (nlh); \
- (skb)->len; })
-
-#define NLMSG_CANCEL(skb, nlh) \
-({ skb_trim(skb, (unsigned char *) (nlh) - (skb)->data); \
- -1; })
-
-extern int netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
- struct nlmsghdr *nlh,
- int (*dump)(struct sk_buff *skb, struct netlink_callback*),
- int (*done)(struct netlink_callback*));
-
-
-#define NL_NONROOT_RECV 0x1
-#define NL_NONROOT_SEND 0x2
-extern void netlink_set_nonroot(int protocol, unsigned flag);
+#define NLA_ALIGNTO 4
+#define NLA_ALIGN(len) (((len) + NLA_ALIGNTO - 1) & ~(NLA_ALIGNTO - 1))
+#define NLA_HDRLEN ((int) NLA_ALIGN(sizeof(struct nlattr)))
-#endif /* __KERNEL__ */
-#endif /* __LINUX_NETLINK_H */
+#endif /* _UAPI__LINUX_NETLINK_H */
diff --git a/src/include/linux/rtnetlink.h b/src/include/linux/rtnetlink.h
index 56835d8bd..56f36a19c 100644
--- a/src/include/linux/rtnetlink.h
+++ b/src/include/linux/rtnetlink.h
@@ -1,7 +1,17 @@
-#ifndef __LINUX_RTNETLINK_H
-#define __LINUX_RTNETLINK_H
+#ifndef _UAPI__LINUX_RTNETLINK_H
+#define _UAPI__LINUX_RTNETLINK_H
#include "netlink.h"
+#include <linux/if_link.h>
+#include <linux/if_addr.h>
+#include <linux/neighbour.h>
+
+/* rtnetlink families. Values up to 127 are reserved for real address
+ * families, values above 128 may be used arbitrarily.
+ */
+#define RTNL_FAMILY_IPMR 128
+#define RTNL_FAMILY_IP6MR 129
+#define RTNL_FAMILY_MAX 129
/****
* Routing/neighbour discovery messages.
@@ -80,8 +90,6 @@ enum {
RTM_NEWPREFIX = 52,
#define RTM_NEWPREFIX RTM_NEWPREFIX
- RTM_GETPREFIX = 54,
-#define RTM_GETPREFIX RTM_GETPREFIX
RTM_GETMULTICAST = 58,
#define RTM_GETMULTICAST RTM_GETMULTICAST
@@ -96,6 +104,40 @@ enum {
RTM_SETNEIGHTBL,
#define RTM_SETNEIGHTBL RTM_SETNEIGHTBL
+ RTM_NEWNDUSEROPT = 68,
+#define RTM_NEWNDUSEROPT RTM_NEWNDUSEROPT
+
+ RTM_NEWADDRLABEL = 72,
+#define RTM_NEWADDRLABEL RTM_NEWADDRLABEL
+ RTM_DELADDRLABEL,
+#define RTM_DELADDRLABEL RTM_DELADDRLABEL
+ RTM_GETADDRLABEL,
+#define RTM_GETADDRLABEL RTM_GETADDRLABEL
+
+ RTM_GETDCB = 78,
+#define RTM_GETDCB RTM_GETDCB
+ RTM_SETDCB,
+#define RTM_SETDCB RTM_SETDCB
+
+ RTM_NEWNETCONF = 80,
+#define RTM_NEWNETCONF RTM_NEWNETCONF
+ RTM_GETNETCONF = 82,
+#define RTM_GETNETCONF RTM_GETNETCONF
+
+ RTM_NEWMDB = 84,
+#define RTM_NEWMDB RTM_NEWMDB
+ RTM_DELMDB = 85,
+#define RTM_DELMDB RTM_DELMDB
+ RTM_GETMDB = 86,
+#define RTM_GETMDB RTM_GETMDB
+
+ RTM_NEWNSID = 88,
+#define RTM_NEWNSID RTM_NEWNSID
+ RTM_DELNSID = 89,
+#define RTM_DELNSID RTM_DELNSID
+ RTM_GETNSID = 90,
+#define RTM_GETNSID RTM_GETNSID
+
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
};
@@ -110,8 +152,7 @@ enum {
with attribute type.
*/
-struct rtattr
-{
+struct rtattr {
unsigned short rta_len;
unsigned short rta_type;
};
@@ -137,8 +178,7 @@ struct rtattr
* Definitions used in routing table administration.
****/
-struct rtmsg
-{
+struct rtmsg {
unsigned char rtm_family;
unsigned char rtm_dst_len;
unsigned char rtm_src_len;
@@ -154,8 +194,7 @@ struct rtmsg
/* rtm_type */
-enum
-{
+enum {
RTN_UNSPEC,
RTN_UNICAST, /* Gateway or direct route */
RTN_LOCAL, /* Accept locally */
@@ -200,6 +239,9 @@ enum
#define RTPROT_DNROUTED 13 /* DECnet routing daemon */
#define RTPROT_XORP 14 /* XORP */
#define RTPROT_NTK 15 /* Netsukuku */
+#define RTPROT_DHCP 16 /* DHCP client */
+#define RTPROT_MROUTED 17 /* Multicast daemon */
+#define RTPROT_BABEL 42 /* Babel daemon */
/* rtm_scope
@@ -212,8 +254,7 @@ enum
could be assigned a value between UNIVERSE and LINK.
*/
-enum rt_scope_t
-{
+enum rt_scope_t {
RT_SCOPE_UNIVERSE=0,
/* User defined values */
RT_SCOPE_SITE=200,
@@ -231,23 +272,20 @@ enum rt_scope_t
/* Reserved table identifiers */
-enum rt_class_t
-{
+enum rt_class_t {
RT_TABLE_UNSPEC=0,
/* User defined values */
+ RT_TABLE_COMPAT=252,
RT_TABLE_DEFAULT=253,
RT_TABLE_MAIN=254,
RT_TABLE_LOCAL=255,
- __RT_TABLE_MAX
+ RT_TABLE_MAX=0xFFFFFFFF
};
-#define RT_TABLE_MAX (__RT_TABLE_MAX - 1)
-
/* Routing message attributes */
-enum rtattr_type_t
-{
+enum rtattr_type_t {
RTA_UNSPEC,
RTA_DST,
RTA_SRC,
@@ -258,12 +296,17 @@ enum rtattr_type_t
RTA_PREFSRC,
RTA_METRICS,
RTA_MULTIPATH,
- RTA_PROTOINFO,
+ RTA_PROTOINFO, /* no longer used */
RTA_FLOW,
RTA_CACHEINFO,
- RTA_SESSION,
- RTA_MP_ALGO,
+ RTA_SESSION, /* no longer used */
+ RTA_MP_ALGO, /* no longer used */
RTA_TABLE,
+ RTA_MARK,
+ RTA_MFC_STATS,
+ RTA_VIA,
+ RTA_NEWDST,
+ RTA_PREF,
__RTA_MAX
};
@@ -281,8 +324,7 @@ enum rtattr_type_t
* and rtt for different paths from multipath.
*/
-struct rtnexthop
-{
+struct rtnexthop {
unsigned short rtnh_len;
unsigned char rtnh_flags;
unsigned char rtnh_hops;
@@ -294,6 +336,10 @@ struct rtnexthop
#define RTNH_F_DEAD 1 /* Nexthop is dead (used by multipath) */
#define RTNH_F_PERVASIVE 2 /* Do recursive gateway lookup */
#define RTNH_F_ONLINK 4 /* Gateway is forced on link */
+#define RTNH_F_OFFLOAD 8 /* offloaded route */
+#define RTNH_F_LINKDOWN 16 /* carrier-down on nexthop */
+
+#define RTNH_COMPARE_MASK (RTNH_F_DEAD | RTNH_F_LINKDOWN)
/* Macros to handle hexthops */
@@ -306,10 +352,15 @@ struct rtnexthop
#define RTNH_SPACE(len) RTNH_ALIGN(RTNH_LENGTH(len))
#define RTNH_DATA(rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0)))
+/* RTA_VIA */
+struct rtvia {
+ __kernel_sa_family_t rtvia_family;
+ __u8 rtvia_addr[0];
+};
+
/* RTM_CACHEINFO */
-struct rta_cacheinfo
-{
+struct rta_cacheinfo {
__u32 rta_clntref;
__u32 rta_lastuse;
__s32 rta_expires;
@@ -324,8 +375,7 @@ struct rta_cacheinfo
/* RTM_METRICS --- array of struct rtattr with types of RTAX_* */
-enum
-{
+enum {
RTAX_UNSPEC,
#define RTAX_UNSPEC RTAX_UNSPEC
RTAX_LOCK,
@@ -352,6 +402,14 @@ enum
#define RTAX_INITCWND RTAX_INITCWND
RTAX_FEATURES,
#define RTAX_FEATURES RTAX_FEATURES
+ RTAX_RTO_MIN,
+#define RTAX_RTO_MIN RTAX_RTO_MIN
+ RTAX_INITRWND,
+#define RTAX_INITRWND RTAX_INITRWND
+ RTAX_QUICKACK,
+#define RTAX_QUICKACK RTAX_QUICKACK
+ RTAX_CC_ALGO,
+#define RTAX_CC_ALGO RTAX_CC_ALGO
__RTAX_MAX
};
@@ -362,8 +420,7 @@ enum
#define RTAX_FEATURE_TIMESTAMP 0x00000004
#define RTAX_FEATURE_ALLFRAG 0x00000008
-struct rta_session
-{
+struct rta_session {
__u8 proto;
__u8 pad1;
__u16 pad2;
@@ -384,232 +441,17 @@ struct rta_session
} u;
};
-
-/*********************************************************
- * Interface address.
- ****/
-
-struct ifaddrmsg
-{
- unsigned char ifa_family;
- unsigned char ifa_prefixlen; /* The prefix length */
- unsigned char ifa_flags; /* Flags */
- unsigned char ifa_scope; /* See above */
- int ifa_index; /* Link index */
-};
-
-enum
-{
- IFA_UNSPEC,
- IFA_ADDRESS,
- IFA_LOCAL,
- IFA_LABEL,
- IFA_BROADCAST,
- IFA_ANYCAST,
- IFA_CACHEINFO,
- IFA_MULTICAST,
- __IFA_MAX
-};
-
-#define IFA_MAX (__IFA_MAX - 1)
-
-/* ifa_flags */
-
-#define IFA_F_SECONDARY 0x01
-#define IFA_F_TEMPORARY IFA_F_SECONDARY
-
-#define IFA_F_DEPRECATED 0x20
-#define IFA_F_TENTATIVE 0x40
-#define IFA_F_PERMANENT 0x80
-
-struct ifa_cacheinfo
-{
- __u32 ifa_prefered;
- __u32 ifa_valid;
- __u32 cstamp; /* created timestamp, hundredths of seconds */
- __u32 tstamp; /* updated timestamp, hundredths of seconds */
-};
-
-
-#define IFA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifaddrmsg))))
-#define IFA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifaddrmsg))
-
-/*
- Important comment:
- IFA_ADDRESS is prefix address, rather than local interface address.
- It makes no difference for normally configured broadcast interfaces,
- but for point-to-point IFA_ADDRESS is DESTINATION address,
- local address is supplied in IFA_LOCAL attribute.
- */
-
-/**************************************************************
- * Neighbour discovery.
- ****/
-
-struct ndmsg
-{
- unsigned char ndm_family;
- unsigned char ndm_pad1;
- unsigned short ndm_pad2;
- int ndm_ifindex; /* Link index */
- __u16 ndm_state;
- __u8 ndm_flags;
- __u8 ndm_type;
-};
-
-enum
-{
- NDA_UNSPEC,
- NDA_DST,
- NDA_LLADDR,
- NDA_CACHEINFO,
- NDA_PROBES,
- __NDA_MAX
-};
-
-#define NDA_MAX (__NDA_MAX - 1)
-
-#define NDA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ndmsg))))
-#define NDA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndmsg))
-
-/*
- * Neighbor Cache Entry Flags
- */
-
-#define NTF_PROXY 0x08 /* == ATF_PUBL */
-#define NTF_ROUTER 0x80
-
-/*
- * Neighbor Cache Entry States.
- */
-
-#define NUD_INCOMPLETE 0x01
-#define NUD_REACHABLE 0x02
-#define NUD_STALE 0x04
-#define NUD_DELAY 0x08
-#define NUD_PROBE 0x10
-#define NUD_FAILED 0x20
-
-/* Dummy states */
-#define NUD_NOARP 0x40
-#define NUD_PERMANENT 0x80
-#define NUD_NONE 0x00
-
-
-struct nda_cacheinfo
-{
- __u32 ndm_confirmed;
- __u32 ndm_used;
- __u32 ndm_updated;
- __u32 ndm_refcnt;
-};
-
-
-/*****************************************************************
- * Neighbour tables specific messages.
- *
- * To retrieve the neighbour tables send RTM_GETNEIGHTBL with the
- * NLM_F_DUMP flag set. Every neighbour table configuration is
- * spread over multiple messages to avoid running into message
- * size limits on systems with many interfaces. The first message
- * in the sequence transports all not device specific data such as
- * statistics, configuration, and the default parameter set.
- * This message is followed by 0..n messages carrying device
- * specific parameter sets.
- * Although the ordering should be sufficient, NDTA_NAME can be
- * used to identify sequences. The initial message can be identified
- * by checking for NDTA_CONFIG. The device specific messages do
- * not contain this TLV but have NDTPA_IFINDEX set to the
- * corresponding interface index.
- *
- * To change neighbour table attributes, send RTM_SETNEIGHTBL
- * with NDTA_NAME set. Changeable attribute include NDTA_THRESH[1-3],
- * NDTA_GC_INTERVAL, and all TLVs in NDTA_PARMS unless marked
- * otherwise. Device specific parameter sets can be changed by
- * setting NDTPA_IFINDEX to the interface index of the corresponding
- * device.
- ****/
-
-struct ndt_stats
-{
- __u64 ndts_allocs;
- __u64 ndts_destroys;
- __u64 ndts_hash_grows;
- __u64 ndts_res_failed;
- __u64 ndts_lookups;
- __u64 ndts_hits;
- __u64 ndts_rcv_probes_mcast;
- __u64 ndts_rcv_probes_ucast;
- __u64 ndts_periodic_gc_runs;
- __u64 ndts_forced_gc_runs;
-};
-
-enum {
- NDTPA_UNSPEC,
- NDTPA_IFINDEX, /* __u32, unchangeable */
- NDTPA_REFCNT, /* __u32, read-only */
- NDTPA_REACHABLE_TIME, /* __u64, read-only, msecs */
- NDTPA_BASE_REACHABLE_TIME, /* __u64, msecs */
- NDTPA_RETRANS_TIME, /* __u64, msecs */
- NDTPA_GC_STALETIME, /* __u64, msecs */
- NDTPA_DELAY_PROBE_TIME, /* __u64, msecs */
- NDTPA_QUEUE_LEN, /* __u32 */
- NDTPA_APP_PROBES, /* __u32 */
- NDTPA_UCAST_PROBES, /* __u32 */
- NDTPA_MCAST_PROBES, /* __u32 */
- NDTPA_ANYCAST_DELAY, /* __u64, msecs */
- NDTPA_PROXY_DELAY, /* __u64, msecs */
- NDTPA_PROXY_QLEN, /* __u32 */
- NDTPA_LOCKTIME, /* __u64, msecs */
- __NDTPA_MAX
-};
-#define NDTPA_MAX (__NDTPA_MAX - 1)
-
-struct ndtmsg
-{
- __u8 ndtm_family;
- __u8 ndtm_pad1;
- __u16 ndtm_pad2;
-};
-
-struct ndt_config
-{
- __u16 ndtc_key_len;
- __u16 ndtc_entry_size;
- __u32 ndtc_entries;
- __u32 ndtc_last_flush; /* delta to now in msecs */
- __u32 ndtc_last_rand; /* delta to now in msecs */
- __u32 ndtc_hash_rnd;
- __u32 ndtc_hash_mask;
- __u32 ndtc_hash_chain_gc;
- __u32 ndtc_proxy_qlen;
-};
-
-enum {
- NDTA_UNSPEC,
- NDTA_NAME, /* char *, unchangeable */
- NDTA_THRESH1, /* __u32 */
- NDTA_THRESH2, /* __u32 */
- NDTA_THRESH3, /* __u32 */
- NDTA_CONFIG, /* struct ndt_config, read-only */
- NDTA_PARMS, /* nested TLV NDTPA_* */
- NDTA_STATS, /* struct ndt_stats, read-only */
- NDTA_GC_INTERVAL, /* __u64, msecs */
- __NDTA_MAX
+struct rta_mfc_stats {
+ __u64 mfcs_packets;
+ __u64 mfcs_bytes;
+ __u64 mfcs_wrong_if;
};
-#define NDTA_MAX (__NDTA_MAX - 1)
-
-#define NDTA_RTA(r) ((struct rtattr*)(((char*)(r)) + \
- NLMSG_ALIGN(sizeof(struct ndtmsg))))
-#define NDTA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ndtmsg))
-
/****
* General form of address family dependent message.
****/
-struct rtgenmsg
-{
+struct rtgenmsg {
unsigned char rtgen_family;
};
@@ -622,8 +464,7 @@ struct rtgenmsg
* on network protocol.
*/
-struct ifinfomsg
-{
+struct ifinfomsg {
unsigned char ifi_family;
unsigned char __ifi_pad;
unsigned short ifi_type; /* ARPHRD_* */
@@ -636,8 +477,7 @@ struct ifinfomsg
* prefix information
****/
-struct prefixmsg
-{
+struct prefixmsg {
unsigned char prefix_family;
unsigned char prefix_pad1;
unsigned short prefix_pad2;
@@ -658,151 +498,17 @@ enum
#define PREFIX_MAX (__PREFIX_MAX - 1)
-struct prefix_cacheinfo
-{
+struct prefix_cacheinfo {
__u32 preferred_time;
__u32 valid_time;
};
-/* The struct should be in sync with struct net_device_stats */
-struct rtnl_link_stats
-{
- __u32 rx_packets; /* total packets received */
- __u32 tx_packets; /* total packets transmitted */
- __u32 rx_bytes; /* total bytes received */
- __u32 tx_bytes; /* total bytes transmitted */
- __u32 rx_errors; /* bad packets received */
- __u32 tx_errors; /* packet transmit problems */
- __u32 rx_dropped; /* no space in linux buffers */
- __u32 tx_dropped; /* no space available in linux */
- __u32 multicast; /* multicast packets received */
- __u32 collisions;
-
- /* detailed rx_errors: */
- __u32 rx_length_errors;
- __u32 rx_over_errors; /* receiver ring buff overflow */
- __u32 rx_crc_errors; /* recved pkt with crc error */
- __u32 rx_frame_errors; /* recv'd frame alignment error */
- __u32 rx_fifo_errors; /* recv'r fifo overrun */
- __u32 rx_missed_errors; /* receiver missed packet */
-
- /* detailed tx_errors */
- __u32 tx_aborted_errors;
- __u32 tx_carrier_errors;
- __u32 tx_fifo_errors;
- __u32 tx_heartbeat_errors;
- __u32 tx_window_errors;
-
- /* for cslip etc */
- __u32 rx_compressed;
- __u32 tx_compressed;
-};
-
-/* The struct should be in sync with struct ifmap */
-struct rtnl_link_ifmap
-{
- __u64 mem_start;
- __u64 mem_end;
- __u64 base_addr;
- __u16 irq;
- __u8 dma;
- __u8 port;
-};
-
-enum
-{
- IFLA_UNSPEC,
- IFLA_ADDRESS,
- IFLA_BROADCAST,
- IFLA_IFNAME,
- IFLA_MTU,
- IFLA_LINK,
- IFLA_QDISC,
- IFLA_STATS,
- IFLA_COST,
-#define IFLA_COST IFLA_COST
- IFLA_PRIORITY,
-#define IFLA_PRIORITY IFLA_PRIORITY
- IFLA_MASTER,
-#define IFLA_MASTER IFLA_MASTER
- IFLA_WIRELESS, /* Wireless Extension event - see wireless.h */
-#define IFLA_WIRELESS IFLA_WIRELESS
- IFLA_PROTINFO, /* Protocol specific information for a link */
-#define IFLA_PROTINFO IFLA_PROTINFO
- IFLA_TXQLEN,
-#define IFLA_TXQLEN IFLA_TXQLEN
- IFLA_MAP,
-#define IFLA_MAP IFLA_MAP
- IFLA_WEIGHT,
-#define IFLA_WEIGHT IFLA_WEIGHT
- IFLA_OPERSTATE,
- IFLA_LINKMODE,
- __IFLA_MAX
-};
-
-
-#define IFLA_MAX (__IFLA_MAX - 1)
-
-#define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
-#define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
-
-/* ifi_flags.
-
- IFF_* flags.
-
- The only change is:
- IFF_LOOPBACK, IFF_BROADCAST and IFF_POINTOPOINT are
- more not changeable by user. They describe link media
- characteristics and set by device driver.
-
- Comments:
- - Combination IFF_BROADCAST|IFF_POINTOPOINT is invalid
- - If neither of these three flags are set;
- the interface is NBMA.
-
- - IFF_MULTICAST does not mean anything special:
- multicasts can be used on all not-NBMA links.
- IFF_MULTICAST means that this media uses special encapsulation
- for multicast frames. Apparently, all IFF_POINTOPOINT and
- IFF_BROADCAST devices are able to use multicasts too.
- */
-
-/* IFLA_LINK.
- For usual devices it is equal ifi_index.
- If it is a "virtual interface" (f.e. tunnel), ifi_link
- can point to real physical interface (f.e. for bandwidth calculations),
- or maybe 0, what means, that real media is unknown (usual
- for IPIP tunnels, when route to endpoint is allowed to change)
- */
-
-/* Subtype attributes for IFLA_PROTINFO */
-enum
-{
- IFLA_INET6_UNSPEC,
- IFLA_INET6_FLAGS, /* link flags */
- IFLA_INET6_CONF, /* sysctl parameters */
- IFLA_INET6_STATS, /* statistics */
- IFLA_INET6_MCAST, /* MC things. What of them? */
- IFLA_INET6_CACHEINFO, /* time values and max reasm size */
- __IFLA_INET6_MAX
-};
-
-#define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
-
-struct ifla_cacheinfo
-{
- __u32 max_reasm_len;
- __u32 tstamp; /* ipv6InterfaceTable updated timestamp */
- __u32 reachable_time;
- __u32 retrans_time;
-};
/*****************************************************************
* Traffic control messages.
****/
-struct tcmsg
-{
+struct tcmsg {
unsigned char tcm_family;
unsigned char tcm__pad1;
unsigned short tcm__pad2;
@@ -812,8 +518,7 @@ struct tcmsg
__u32 tcm_info;
};
-enum
-{
+enum {
TCA_UNSPEC,
TCA_KIND,
TCA_OPTIONS,
@@ -822,6 +527,7 @@ enum
TCA_RATE,
TCA_FCNT,
TCA_STATS2,
+ TCA_STAB,
__TCA_MAX
};
@@ -830,6 +536,30 @@ enum
#define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg))))
#define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg))
+/********************************************************************
+ * Neighbor Discovery userland options
+ ****/
+
+struct nduseroptmsg {
+ unsigned char nduseropt_family;
+ unsigned char nduseropt_pad1;
+ unsigned short nduseropt_opts_len; /* Total length of options */
+ int nduseropt_ifindex;
+ __u8 nduseropt_icmp_type;
+ __u8 nduseropt_icmp_code;
+ unsigned short nduseropt_pad2;
+ unsigned int nduseropt_pad3;
+ /* Followed by one or more ND options */
+};
+
+enum {
+ NDUSEROPT_UNSPEC,
+ NDUSEROPT_SRCADDR,
+ __NDUSEROPT_MAX
+};
+
+#define NDUSEROPT_MAX (__NDUSEROPT_MAX - 1)
+
#ifndef __KERNEL__
/* RTnetlink multicast groups - backwards compatibility for userspace */
#define RTMGRP_LINK 1
@@ -886,17 +616,37 @@ enum rtnetlink_groups {
RTNLGRP_NOP2,
RTNLGRP_DECnet_ROUTE,
#define RTNLGRP_DECnet_ROUTE RTNLGRP_DECnet_ROUTE
- RTNLGRP_NOP3,
+ RTNLGRP_DECnet_RULE,
+#define RTNLGRP_DECnet_RULE RTNLGRP_DECnet_RULE
RTNLGRP_NOP4,
RTNLGRP_IPV6_PREFIX,
#define RTNLGRP_IPV6_PREFIX RTNLGRP_IPV6_PREFIX
+ RTNLGRP_IPV6_RULE,
+#define RTNLGRP_IPV6_RULE RTNLGRP_IPV6_RULE
+ RTNLGRP_ND_USEROPT,
+#define RTNLGRP_ND_USEROPT RTNLGRP_ND_USEROPT
+ RTNLGRP_PHONET_IFADDR,
+#define RTNLGRP_PHONET_IFADDR RTNLGRP_PHONET_IFADDR
+ RTNLGRP_PHONET_ROUTE,
+#define RTNLGRP_PHONET_ROUTE RTNLGRP_PHONET_ROUTE
+ RTNLGRP_DCB,
+#define RTNLGRP_DCB RTNLGRP_DCB
+ RTNLGRP_IPV4_NETCONF,
+#define RTNLGRP_IPV4_NETCONF RTNLGRP_IPV4_NETCONF
+ RTNLGRP_IPV6_NETCONF,
+#define RTNLGRP_IPV6_NETCONF RTNLGRP_IPV6_NETCONF
+ RTNLGRP_MDB,
+#define RTNLGRP_MDB RTNLGRP_MDB
+ RTNLGRP_MPLS_ROUTE,
+#define RTNLGRP_MPLS_ROUTE RTNLGRP_MPLS_ROUTE
+ RTNLGRP_NSID,
+#define RTNLGRP_NSID RTNLGRP_NSID
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
/* TC action piece */
-struct tcamsg
-{
+struct tcamsg {
unsigned char tca_family;
unsigned char tca__pad1;
unsigned short tca__pad2;
@@ -906,168 +656,13 @@ struct tcamsg
#define TCA_ACT_TAB 1 /* attr type must be >=1 */
#define TCAA_MAX 1
-/* End of information exported to user level */
-
-#ifdef __KERNEL__
-
-#include <linux/config.h>
-#include <linux/mutex.h>
-
-extern size_t rtattr_strlcpy(char *dest, const struct rtattr *rta, size_t size);
-static __inline__ int rtattr_strcmp(const struct rtattr *rta, const char *str)
-{
- int len = strlen(str) + 1;
- return len > rta->rta_len || memcmp(RTA_DATA(rta), str, len);
-}
-
-extern int rtattr_parse(struct rtattr *tb[], int maxattr, struct rtattr *rta, int len);
-
-#define rtattr_parse_nested(tb, max, rta) \
- rtattr_parse((tb), (max), RTA_DATA((rta)), RTA_PAYLOAD((rta)))
-
-extern struct sock *rtnl;
-
-struct rtnetlink_link
-{
- int (*doit)(struct sk_buff *, struct nlmsghdr*, void *attr);
- int (*dumpit)(struct sk_buff *, struct netlink_callback *cb);
-};
-
-extern struct rtnetlink_link * rtnetlink_links[NPROTO];
-extern int rtnetlink_send(struct sk_buff *skb, __u32 pid, __u32 group, int echo);
-extern int rtnetlink_put_metrics(struct sk_buff *skb, __u32 *metrics);
+/* New extended info filters for IFLA_EXT_MASK */
+#define RTEXT_FILTER_VF (1 << 0)
+#define RTEXT_FILTER_BRVLAN (1 << 1)
+#define RTEXT_FILTER_BRVLAN_COMPRESSED (1 << 2)
-extern void __rta_fill(struct sk_buff *skb, int attrtype, int attrlen, const void *data);
-
-#define RTA_PUT(skb, attrtype, attrlen, data) \
-({ if (unlikely(skb_tailroom(skb) < (int)RTA_SPACE(attrlen))) \
- goto rtattr_failure; \
- __rta_fill(skb, attrtype, attrlen, data); })
-
-#define RTA_APPEND(skb, attrlen, data) \
-({ if (unlikely(skb_tailroom(skb) < (int)(attrlen))) \
- goto rtattr_failure; \
- memcpy(skb_put(skb, attrlen), data, attrlen); })
-
-#define RTA_PUT_NOHDR(skb, attrlen, data) \
-({ RTA_APPEND(skb, RTA_ALIGN(attrlen), data); \
- memset(skb->tail - (RTA_ALIGN(attrlen) - attrlen), 0, \
- RTA_ALIGN(attrlen) - attrlen); })
-
-#define RTA_PUT_U8(skb, attrtype, value) \
-({ __u8 _tmp = (value); \
- RTA_PUT(skb, attrtype, sizeof(__u8), &_tmp); })
-
-#define RTA_PUT_U16(skb, attrtype, value) \
-({ __u16 _tmp = (value); \
- RTA_PUT(skb, attrtype, sizeof(__u16), &_tmp); })
-
-#define RTA_PUT_U32(skb, attrtype, value) \
-({ __u32 _tmp = (value); \
- RTA_PUT(skb, attrtype, sizeof(__u32), &_tmp); })
-
-#define RTA_PUT_U64(skb, attrtype, value) \
-({ __u64 _tmp = (value); \
- RTA_PUT(skb, attrtype, sizeof(__u64), &_tmp); })
-
-#define RTA_PUT_SECS(skb, attrtype, value) \
- RTA_PUT_U64(skb, attrtype, (value) / HZ)
-
-#define RTA_PUT_MSECS(skb, attrtype, value) \
- RTA_PUT_U64(skb, attrtype, jiffies_to_msecs(value))
-
-#define RTA_PUT_STRING(skb, attrtype, value) \
- RTA_PUT(skb, attrtype, strlen(value) + 1, value)
-
-#define RTA_PUT_FLAG(skb, attrtype) \
- RTA_PUT(skb, attrtype, 0, NULL);
-
-#define RTA_NEST(skb, type) \
-({ struct rtattr *__start = (struct rtattr *) (skb)->tail; \
- RTA_PUT(skb, type, 0, NULL); \
- __start; })
-
-#define RTA_NEST_END(skb, start) \
-({ (start)->rta_len = ((skb)->tail - (unsigned char *) (start)); \
- (skb)->len; })
-
-#define RTA_NEST_CANCEL(skb, start) \
-({ if (start) \
- skb_trim(skb, (unsigned char *) (start) - (skb)->data); \
- -1; })
-
-#define RTA_GET_U8(rta) \
-({ if (!rta || RTA_PAYLOAD(rta) < sizeof(__u8)) \
- goto rtattr_failure; \
- *(__u8 *) RTA_DATA(rta); })
-
-#define RTA_GET_U16(rta) \
-({ if (!rta || RTA_PAYLOAD(rta) < sizeof(__u16)) \
- goto rtattr_failure; \
- *(__u16 *) RTA_DATA(rta); })
-
-#define RTA_GET_U32(rta) \
-({ if (!rta || RTA_PAYLOAD(rta) < sizeof(__u32)) \
- goto rtattr_failure; \
- *(__u32 *) RTA_DATA(rta); })
-
-#define RTA_GET_U64(rta) \
-({ __u64 _tmp; \
- if (!rta || RTA_PAYLOAD(rta) < sizeof(__u64)) \
- goto rtattr_failure; \
- memcpy(&_tmp, RTA_DATA(rta), sizeof(_tmp)); \
- _tmp; })
+/* End of information exported to user level */
-#define RTA_GET_FLAG(rta) (!!(rta))
-#define RTA_GET_SECS(rta) ((unsigned long) RTA_GET_U64(rta) * HZ)
-#define RTA_GET_MSECS(rta) (msecs_to_jiffies((unsigned long) RTA_GET_U64(rta)))
-static __inline__ struct rtattr *
-__rta_reserve(struct sk_buff *skb, int attrtype, int attrlen)
-{
- struct rtattr *rta;
- int size = RTA_LENGTH(attrlen);
-
- rta = (struct rtattr*)skb_put(skb, RTA_ALIGN(size));
- rta->rta_type = attrtype;
- rta->rta_len = size;
- memset(RTA_DATA(rta) + attrlen, 0, RTA_ALIGN(size) - size);
- return rta;
-}
-
-#define __RTA_PUT(skb, attrtype, attrlen) \
-({ if (unlikely(skb_tailroom(skb) < (int)RTA_SPACE(attrlen))) \
- goto rtattr_failure; \
- __rta_reserve(skb, attrtype, attrlen); })
-
-extern void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change);
-
-/* RTNL is used as a global lock for all changes to network configuration */
-extern void rtnl_lock(void);
-extern void rtnl_unlock(void);
-extern int rtnl_trylock(void);
-
-extern void rtnetlink_init(void);
-extern void __rtnl_unlock(void);
-
-#define ASSERT_RTNL() do { \
- if (unlikely(rtnl_trylock())) { \
- rtnl_unlock(); \
- printk(KERN_ERR "RTNL: assertion failed at %s (%d)\n", \
- __FILE__, __LINE__); \
- dump_stack(); \
- } \
-} while(0)
-
-#define BUG_TRAP(x) do { \
- if (unlikely(!(x))) { \
- printk(KERN_ERR "KERNEL: assertion (%s) failed at %s (%d)\n", \
- #x, __FILE__ , __LINE__); \
- } \
-} while(0)
-
-#endif /* __KERNEL__ */
-
-
-#endif /* __LINUX_RTNETLINK_H */
+#endif /* _UAPI__LINUX_RTNETLINK_H */
diff --git a/src/include/linux/types.h b/src/include/linux/types.h
deleted file mode 100644
index 22cfdc05e..000000000
--- a/src/include/linux/types.h
+++ /dev/null
@@ -1,172 +0,0 @@
-#ifndef _LINUX_TYPES_H
-#define _LINUX_TYPES_H
-
-
-#include <linux/posix_types.h>
-#include <asm/types.h>
-
-#ifndef __KERNEL_STRICT_NAMES
-
-typedef __u32 __kernel_dev_t;
-
-typedef __kernel_fd_set fd_set;
-typedef __kernel_dev_t dev_t;
-typedef __kernel_ino_t ino_t;
-typedef __kernel_mode_t mode_t;
-typedef __kernel_nlink_t nlink_t;
-typedef __kernel_off_t off_t;
-typedef __kernel_pid_t pid_t;
-typedef __kernel_daddr_t daddr_t;
-typedef __kernel_key_t key_t;
-typedef __kernel_suseconds_t suseconds_t;
-typedef __kernel_timer_t timer_t;
-typedef __kernel_clockid_t clockid_t;
-typedef __kernel_mqd_t mqd_t;
-
-typedef __kernel_uid_t uid_t;
-typedef __kernel_gid_t gid_t;
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __kernel_loff_t loff_t;
-#endif
-
-/*
- * The following typedefs are also protected by individual ifdefs for
- * historical reasons:
- */
-#ifndef _SIZE_T
-#define _SIZE_T
-typedef __kernel_size_t size_t;
-#endif
-
-#ifndef _SSIZE_T
-#define _SSIZE_T
-typedef __kernel_ssize_t ssize_t;
-#endif
-
-#ifndef _PTRDIFF_T
-#define _PTRDIFF_T
-typedef __kernel_ptrdiff_t ptrdiff_t;
-#endif
-
-#ifndef _TIME_T
-#define _TIME_T
-typedef __kernel_time_t time_t;
-#endif
-
-#ifndef _CLOCK_T
-#define _CLOCK_T
-typedef __kernel_clock_t clock_t;
-#endif
-
-#ifndef _CADDR_T
-#define _CADDR_T
-typedef __kernel_caddr_t caddr_t;
-#endif
-
-/* bsd */
-typedef unsigned char u_char;
-typedef unsigned short u_short;
-typedef unsigned int u_int;
-typedef unsigned long u_long;
-
-/* sysv */
-typedef unsigned char unchar;
-typedef unsigned short ushort;
-typedef unsigned int uint;
-typedef unsigned long ulong;
-
-#ifndef __BIT_TYPES_DEFINED__
-#define __BIT_TYPES_DEFINED__
-
-typedef __u8 u_int8_t;
-typedef __s8 int8_t;
-typedef __u16 u_int16_t;
-typedef __s16 int16_t;
-typedef __u32 u_int32_t;
-typedef __s32 int32_t;
-
-#endif /* !(__BIT_TYPES_DEFINED__) */
-
-typedef __u8 uint8_t;
-typedef __u16 uint16_t;
-typedef __u32 uint32_t;
-
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __u64 uint64_t;
-typedef __u64 u_int64_t;
-typedef __s64 int64_t;
-#endif
-
-/* this is a special 64bit data type that is 8-byte aligned */
-#define aligned_u64 unsigned long long __attribute__((aligned(8)))
-#define aligned_be64 __be64 __attribute__((aligned(8)))
-#define aligned_le64 __le64 __attribute__((aligned(8)))
-
-/**
- * The type used for indexing onto a disc or disc partition.
- *
- * Linux always considers sectors to be 512 bytes long independently
- * of the devices real block size.
- */
-#ifdef CONFIG_LBD
-typedef u64 sector_t;
-#else
-typedef unsigned long sector_t;
-#endif
-
-/*
- * The type of the inode's block count.
- */
-#ifdef CONFIG_LSF
-typedef u64 blkcnt_t;
-#else
-typedef unsigned long blkcnt_t;
-#endif
-
-/*
- * The type of an index into the pagecache. Use a #define so asm/types.h
- * can override it.
- */
-#ifndef pgoff_t
-#define pgoff_t unsigned long
-#endif
-
-#endif /* __KERNEL_STRICT_NAMES */
-
-/*
- * Below are truly Linux-specific types that should never collide with
- * any application/library that wants linux/types.h.
- */
-
-#ifdef __CHECKER__
-#define __bitwise__ __attribute__((bitwise))
-#else
-#define __bitwise__
-#endif
-#ifdef __CHECK_ENDIAN__
-#define __bitwise __bitwise__
-#else
-#define __bitwise
-#endif
-
-typedef __u16 __bitwise __le16;
-typedef __u16 __bitwise __be16;
-typedef __u32 __bitwise __le32;
-typedef __u32 __bitwise __be32;
-#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
-typedef __u64 __bitwise __le64;
-typedef __u64 __bitwise __be64;
-#endif
-typedef __u16 __bitwise __sum16;
-typedef __u32 __bitwise __wsum;
-
-
-struct ustat {
- __kernel_daddr_t f_tfree;
- __kernel_ino_t f_tinode;
- char f_fname[6];
- char f_fpack[6];
-};
-
-#endif /* _LINUX_TYPES_H */
diff --git a/src/ipsec/_ipsec.8 b/src/ipsec/_ipsec.8
index f9c54f8a4..9795451e8 100644
--- a/src/ipsec/_ipsec.8
+++ b/src/ipsec/_ipsec.8
@@ -1,4 +1,4 @@
-.TH IPSEC 8 "2013-10-29" "5.3.1dr1" "strongSwan"
+.TH IPSEC 8 "2013-10-29" "5.3.3dr5" "strongSwan"
.
.SH NAME
.
diff --git a/src/libcharon/config/ike_cfg.c b/src/libcharon/config/ike_cfg.c
index 9464ceb5d..dee9e4c29 100644
--- a/src/libcharon/config/ike_cfg.c
+++ b/src/libcharon/config/ike_cfg.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2012-2015 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -513,6 +514,52 @@ static void parse_addresses(char *str, linked_list_t *hosts,
/**
* Described in header.
*/
+int ike_cfg_get_family(ike_cfg_t *cfg, bool local)
+{
+ private_ike_cfg_t *this = (private_ike_cfg_t*)cfg;
+ enumerator_t *enumerator;
+ host_t *host;
+ char *str;
+ int family = AF_UNSPEC;
+
+ if (local)
+ {
+ enumerator = this->my_hosts->create_enumerator(this->my_hosts);
+ }
+ else
+ {
+ enumerator = this->other_hosts->create_enumerator(this->other_hosts);
+ }
+ while (enumerator->enumerate(enumerator, &str))
+ {
+ if (streq(str, "%any"))
+ { /* ignore %any as its family is undetermined */
+ continue;
+ }
+ host = host_create_from_string(str, 0);
+ if (host)
+ {
+ if (family == AF_UNSPEC)
+ {
+ family = host->get_family(host);
+ }
+ else if (family != host->get_family(host))
+ {
+ /* more than one address family defined */
+ family = AF_UNSPEC;
+ host->destroy(host);
+ break;
+ }
+ }
+ DESTROY_IF(host);
+ }
+ enumerator->destroy(enumerator);
+ return family;
+}
+
+/**
+ * Described in header.
+ */
ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap,
char *me, u_int16_t my_port,
char *other, u_int16_t other_port,
diff --git a/src/libcharon/config/ike_cfg.h b/src/libcharon/config/ike_cfg.h
index adfcabf70..a72960f4f 100644
--- a/src/libcharon/config/ike_cfg.h
+++ b/src/libcharon/config/ike_cfg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2015 Tobias Brunner
* Copyright (C) 2005-2007 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -160,7 +160,7 @@ struct ike_cfg_t {
*
* Returned list and its proposals must be destroyed after use.
*
- * @return list containing all the proposals
+ * @return list containing all the proposals
*/
linked_list_t* (*get_proposals) (ike_cfg_t *this);
@@ -247,11 +247,22 @@ struct ike_cfg_t {
* @param other_port IKE port to use as dest, 500 uses IKEv2 port floating
* @param fragmentation use IKEv1 fragmentation
* @param dscp DSCP value to send IKE packets with
- * @return ike_cfg_t object.
+ * @return ike_cfg_t object.
*/
ike_cfg_t *ike_cfg_create(ike_version_t version, bool certreq, bool force_encap,
char *me, u_int16_t my_port,
char *other, u_int16_t other_port,
fragmentation_t fragmentation, u_int8_t dscp);
+/**
+ * Determine the address family of the local or remtoe address(es). If multiple
+ * families are configured AF_UNSPEC is returned. %any is ignored (%any4|6 are
+ * not though).
+ *
+ * @param this ike config to check
+ * @param local TRUE to check local addresses, FALSE for remote
+ * @return address family of address(es) if distinct
+ */
+int ike_cfg_get_family(ike_cfg_t *this, bool local);
+
#endif /** IKE_CFG_H_ @}*/
diff --git a/src/libcharon/control/controller.c b/src/libcharon/control/controller.c
index fd8349e2f..6dd54b473 100644
--- a/src/libcharon/control/controller.c
+++ b/src/libcharon/control/controller.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2012 Tobias Brunner
+ * Copyright (C) 2011-2015 Tobias Brunner
* Copyright (C) 2007-2011 Martin Willi
* Copyright (C) 2011 revosec AG
* Hochschule fuer Technik Rapperswil
@@ -116,6 +116,11 @@ struct interface_listener_t {
* spinlock to update the IKE_SA handle properly
*/
spinlock_t *lock;
+
+ /**
+ * whether to check limits
+ */
+ bool limits;
};
@@ -358,7 +363,6 @@ METHOD(job_t, initiate_execute, job_requeue_t,
listener->child_cfg->destroy(listener->child_cfg);
peer_cfg->destroy(peer_cfg);
listener->status = FAILED;
- /* release listener */
listener_done(listener);
return JOB_REQUEUE_NONE;
}
@@ -372,6 +376,49 @@ METHOD(job_t, initiate_execute, job_requeue_t,
}
peer_cfg->destroy(peer_cfg);
+ if (listener->limits && ike_sa->get_state(ike_sa) == IKE_CREATED)
+ { /* only check if we are not reusing an IKE_SA */
+ u_int half_open, limit_half_open, limit_job_load;
+
+ half_open = charon->ike_sa_manager->get_half_open_count(
+ charon->ike_sa_manager, NULL, FALSE);
+ limit_half_open = lib->settings->get_int(lib->settings,
+ "%s.init_limit_half_open", 0, lib->ns);
+ limit_job_load = lib->settings->get_int(lib->settings,
+ "%s.init_limit_job_load", 0, lib->ns);
+ if (limit_half_open && half_open >= limit_half_open)
+ {
+ DBG1(DBG_IKE, "abort IKE_SA initiation, half open IKE_SA count of "
+ "%d exceeds limit of %d", half_open, limit_half_open);
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+ ike_sa);
+ listener->child_cfg->destroy(listener->child_cfg);
+ listener->status = INVALID_STATE;
+ listener_done(listener);
+ return JOB_REQUEUE_NONE;
+ }
+ if (limit_job_load)
+ {
+ u_int jobs = 0, i;
+
+ for (i = 0; i < JOB_PRIO_MAX; i++)
+ {
+ jobs += lib->processor->get_job_load(lib->processor, i);
+ }
+ if (jobs > limit_job_load)
+ {
+ DBG1(DBG_IKE, "abort IKE_SA initiation, job load of %d exceeds "
+ "limit of %d", jobs, limit_job_load);
+ charon->ike_sa_manager->checkin_and_destroy(
+ charon->ike_sa_manager, ike_sa);
+ listener->child_cfg->destroy(listener->child_cfg);
+ listener->status = INVALID_STATE;
+ listener_done(listener);
+ return JOB_REQUEUE_NONE;
+ }
+ }
+ }
+
if (ike_sa->initiate(ike_sa, listener->child_cfg, 0, NULL, NULL) == SUCCESS)
{
if (!listener->logger.callback)
@@ -391,7 +438,7 @@ METHOD(job_t, initiate_execute, job_requeue_t,
METHOD(controller_t, initiate, status_t,
private_controller_t *this, peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
- controller_cb_t callback, void *param, u_int timeout)
+ controller_cb_t callback, void *param, u_int timeout, bool limits)
{
interface_job_t *job;
status_t status;
@@ -414,6 +461,7 @@ METHOD(controller_t, initiate, status_t,
.child_cfg = child_cfg,
.peer_cfg = peer_cfg,
.lock = spinlock_create(),
+ .limits = limits,
},
.public = {
.execute = _initiate_execute,
diff --git a/src/libcharon/control/controller.h b/src/libcharon/control/controller.h
index 02f4ebb2b..5ffeac522 100644
--- a/src/libcharon/control/controller.h
+++ b/src/libcharon/control/controller.h
@@ -82,15 +82,18 @@ struct controller_t {
* @param cb logging callback
* @param param parameter to include in each call of cb
* @param timeout timeout in ms to wait for callbacks, 0 to disable
+ * @param limits whether to check limits regarding IKE_SA initiation
* @return
* - SUCCESS, if CHILD_SA established
* - FAILED, if setup failed
* - NEED_MORE, if callback returned FALSE
* - OUT_OF_RES if timed out
+ * - INVALID_STATE if limits prevented initiation
*/
status_t (*initiate)(controller_t *this,
peer_cfg_t *peer_cfg, child_cfg_t *child_cfg,
- controller_cb_t callback, void *param, u_int timeout);
+ controller_cb_t callback, void *param, u_int timeout,
+ bool limits);
/**
* Terminate an IKE_SA and all of its CHILD_SAs.
diff --git a/src/libcharon/daemon.c b/src/libcharon/daemon.c
index b1b8f57f0..316be7611 100644
--- a/src/libcharon/daemon.c
+++ b/src/libcharon/daemon.c
@@ -462,6 +462,10 @@ static void destroy(private_daemon_t *this)
{
this->public.traps->flush(this->public.traps);
}
+ if (this->public.shunts)
+ {
+ this->public.shunts->flush(this->public.shunts);
+ }
if (this->public.sender)
{
this->public.sender->flush(this->public.sender);
diff --git a/src/libcharon/encoding/payloads/fragment_payload.c b/src/libcharon/encoding/payloads/fragment_payload.c
index b861fcc68..7f158f548 100644
--- a/src/libcharon/encoding/payloads/fragment_payload.c
+++ b/src/libcharon/encoding/payloads/fragment_payload.c
@@ -222,4 +222,4 @@ fragment_payload_t *fragment_payload_create_from_data(u_int8_t num, bool last,
this->data = chunk_clone(data);
this->payload_length = get_header_length(this) + data.len;
return &this->public;
-} \ No newline at end of file
+}
diff --git a/src/libcharon/encoding/payloads/proposal_substructure.c b/src/libcharon/encoding/payloads/proposal_substructure.c
index 48dcfeb24..65ce667c7 100644
--- a/src/libcharon/encoding/payloads/proposal_substructure.c
+++ b/src/libcharon/encoding/payloads/proposal_substructure.c
@@ -914,6 +914,11 @@ static void add_to_proposal_v1_ike(proposal_t *proposal,
if (encr != ENCR_UNDEFINED)
{
+ if (encr == ENCR_AES_CBC && !key_length)
+ { /* some implementations don't send a Key Length attribute for
+ * AES-128, early drafts of RFC 3602 allowed that */
+ key_length = 128;
+ }
proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr, key_length);
}
}
@@ -962,6 +967,12 @@ static void add_to_proposal_v1(proposal_t *proposal,
transform->get_transform_id(transform));
if (encr)
{
+ if (encr == ENCR_AES_CBC && !key_length)
+ { /* some implementations don't send a Key Length attribute for
+ * AES-128, early drafts of RFC 3602 allowed that for IKE, some
+ * also seem to do it for ESP */
+ key_length = 128;
+ }
proposal->add_algorithm(proposal, ENCRYPTION_ALGORITHM, encr,
key_length);
}
diff --git a/src/libcharon/network/receiver.c b/src/libcharon/network/receiver.c
index 6902c4847..a2f2016ff 100644
--- a/src/libcharon/network/receiver.c
+++ b/src/libcharon/network/receiver.c
@@ -322,16 +322,18 @@ static bool cookie_required(private_receiver_t *this,
*/
static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
{
- u_int half_open;
+ u_int half_open, half_open_r;
u_int32_t now;
now = time_monotonic(NULL);
half_open = charon->ike_sa_manager->get_half_open_count(
- charon->ike_sa_manager, NULL);
+ charon->ike_sa_manager, NULL, FALSE);
+ half_open_r = charon->ike_sa_manager->get_half_open_count(
+ charon->ike_sa_manager, NULL, TRUE);
/* check for cookies in IKEv2 */
if (message->get_major_version(message) == IKEV2_MAJOR_VERSION &&
- cookie_required(this, half_open, now) && !check_cookie(this, message))
+ cookie_required(this, half_open_r, now) && !check_cookie(this, message))
{
chunk_t cookie;
@@ -372,7 +374,7 @@ static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
/* check if peer has too many IKE_SAs half open */
if (this->block_threshold &&
charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
- message->get_source(message)) >= this->block_threshold)
+ message->get_source(message), TRUE) >= this->block_threshold)
{
DBG1(DBG_NET, "ignoring IKE_SA setup from %H, "
"peer too aggressive", message->get_source(message));
@@ -381,7 +383,7 @@ static bool drop_ike_sa_init(private_receiver_t *this, message_t *message)
/* check if global half open IKE_SA limit reached */
if (this->init_limit_half_open &&
- half_open >= this->init_limit_half_open)
+ half_open >= this->init_limit_half_open)
{
DBG1(DBG_NET, "ignoring IKE_SA setup from %H, half open IKE_SA "
"count of %d exceeds limit of %d", message->get_source(message),
@@ -542,7 +544,9 @@ static job_requeue_t receive_packets(private_receiver_t *this)
if (message->get_request(message) &&
message->get_exchange_type(message) == IKE_SA_INIT)
{
- if (this->initiator_only || drop_ike_sa_init(this, message))
+ id = message->get_ike_sa_id(message);
+ if (this->initiator_only || !id->is_initiator(id) ||
+ drop_ike_sa_init(this, message))
{
message->destroy(message);
return JOB_REQUEUE_DIRECT;
diff --git a/src/libcharon/plugins/eap_radius/eap_radius.c b/src/libcharon/plugins/eap_radius/eap_radius.c
index 60d12dc1d..237f065fa 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius.c
@@ -434,6 +434,9 @@ static void add_nameserver_attribute(eap_radius_provider_t *provider,
case 31: /* MS-Secondary-NBNS-Server */
provider->add_attribute(provider, id, INTERNAL_IP4_NBNS, data);
break;
+ case RAT_FRAMED_IPV6_DNS_SERVER:
+ provider->add_attribute(provider, id, INTERNAL_IP6_DNS, data);
+ break;
}
}
@@ -515,9 +518,10 @@ static void process_cfg_attributes(radius_message_t *msg)
enumerator = msg->create_enumerator(msg);
while (enumerator->enumerate(enumerator, &type, &data))
{
- if (type == RAT_FRAMED_IP_ADDRESS && data.len == 4)
+ if ((type == RAT_FRAMED_IP_ADDRESS && data.len == 4) ||
+ (type == RAT_FRAMED_IPV6_ADDRESS && data.len == 16))
{
- host = host_create_from_chunk(AF_INET, data, 0);
+ host = host_create_from_chunk(AF_UNSPEC, data, 0);
if (host)
{
provider->add_framed_ip(provider,
@@ -529,6 +533,11 @@ static void process_cfg_attributes(radius_message_t *msg)
provider->add_attribute(provider, ike_sa->get_unique_id(ike_sa),
INTERNAL_IP4_NETMASK, data);
}
+ else if (type == RAT_FRAMED_IPV6_DNS_SERVER && data.len == 16)
+ {
+ add_nameserver_attribute(provider,
+ ike_sa->get_unique_id(ike_sa), type, data);
+ }
}
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 cef19305c..4b7260349 100644
--- a/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
+++ b/src/libcharon/plugins/eap_radius/eap_radius_accounting.c
@@ -447,10 +447,8 @@ static void add_ike_sa_parameters(private_eap_radius_accounting_t *this,
vip->get_address(vip));
break;
case AF_INET6:
- /* we currently assign /128 prefixes, only (reserved, length) */
- data = chunk_from_chars(0, 128);
- data = chunk_cata("cc", data, vip->get_address(vip));
- message->add(message, RAT_FRAMED_IPV6_PREFIX, data);
+ message->add(message, RAT_FRAMED_IPV6_ADDRESS,
+ vip->get_address(vip));
break;
default:
break;
@@ -694,6 +692,11 @@ static void send_start(private_eap_radius_accounting_t *this, ike_sa_t *ike_sa)
entry = get_or_create_entry(this, ike_sa->get_id(ike_sa),
ike_sa->get_unique_id(ike_sa));
+ if (entry->start_sent)
+ {
+ this->mutex->unlock(this->mutex);
+ return;
+ }
entry->start_sent = TRUE;
message = radius_message_create(RMC_ACCOUNTING_REQUEST);
@@ -860,11 +863,6 @@ METHOD(listener_t, message_hook, bool,
if (plain && ike_sa->get_state(ike_sa) == IKE_ESTABLISHED &&
!incoming && !message->get_request(message))
{
- if (ike_sa->get_version(ike_sa) == IKEV1 &&
- message->get_exchange_type(message) == TRANSACTION)
- {
- send_start(this, ike_sa);
- }
if (ike_sa->get_version(ike_sa) == IKEV2 &&
message->get_exchange_type(message) == IKE_AUTH)
{
@@ -874,6 +872,17 @@ METHOD(listener_t, message_hook, bool,
return TRUE;
}
+METHOD(listener_t, assign_vips, bool,
+ private_eap_radius_accounting_t *this, ike_sa_t *ike_sa, bool assign)
+{
+ /* start accounting as soon as the virtual IP is set */
+ if (assign && ike_sa->get_version(ike_sa) == IKEV1)
+ {
+ send_start(this, ike_sa);
+ }
+ return TRUE;
+}
+
METHOD(listener_t, ike_rekey, bool,
private_eap_radius_accounting_t *this, ike_sa_t *old, ike_sa_t *new)
{
@@ -1003,6 +1012,7 @@ eap_radius_accounting_t *eap_radius_accounting_create()
.ike_updown = _ike_updown,
.ike_rekey = _ike_rekey,
.message = _message_hook,
+ .assign_vips = _assign_vips,
.child_updown = _child_updown,
.child_rekey = _child_rekey,
.children_migrate = _children_migrate,
diff --git a/src/libcharon/plugins/eap_tnc/eap_tnc.c b/src/libcharon/plugins/eap_tnc/eap_tnc.c
index f70f47ef6..350001bb4 100644
--- a/src/libcharon/plugins/eap_tnc/eap_tnc.c
+++ b/src/libcharon/plugins/eap_tnc/eap_tnc.c
@@ -335,6 +335,10 @@ static eap_tnc_t *eap_tnc_create(identification_t *server,
free(this);
return NULL;
}
+ if (!is_server)
+ {
+ tnccs->set_auth_type(tnccs, TNC_AUTH_X509_CERT);
+ }
this->tnccs = tnccs->get_ref(tnccs);
this->tls_eap = tls_eap_create(type, &tnccs->tls,
EAP_TNC_MAX_MESSAGE_LEN,
diff --git a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
index 66c9deed8..e0b59a681 100644
--- a/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
+++ b/src/libcharon/plugins/eap_ttls/eap_ttls_peer.c
@@ -112,6 +112,13 @@ METHOD(tls_application_t, process, status_t,
eap_data = avp_data;
break;
}
+ else if (eap_len > reader->remaining(reader) + avp_data.len)
+ {
+ /* rough size check, ignoring AVP headers in remaining data */
+ DBG1(DBG_IKE, "EAP packet too large for EAP-TTLS AVP(s)");
+ chunk_free(&avp_data);
+ return FAILED;
+ }
else if (avp_data.len == MAX_RADIUS_ATTRIBUTE_SIZE)
{
/* non-standard: EAP packet segmented into multiple AVPs */
@@ -128,7 +135,7 @@ METHOD(tls_application_t, process, status_t,
if (avp_data.len > eap_data.len - eap_pos)
{
- DBG1(DBG_IKE, "AVP size to large to fit into EAP packet");
+ DBG1(DBG_IKE, "AVP size too large to fit into EAP packet");
chunk_free(&avp_data);
chunk_free(&eap_data);
return FAILED;
diff --git a/src/libcharon/plugins/error_notify/error_notify_listener.c b/src/libcharon/plugins/error_notify/error_notify_listener.c
index 13860fe50..f7a1f49ec 100644
--- a/src/libcharon/plugins/error_notify/error_notify_listener.c
+++ b/src/libcharon/plugins/error_notify/error_notify_listener.c
@@ -96,13 +96,13 @@ METHOD(listener_t, alert, bool,
case ALERT_PROPOSAL_MISMATCH_IKE:
msg.type = htonl(ERROR_NOTIFY_PROPOSAL_MISMATCH_IKE);
list = va_arg(args, linked_list_t*);
- snprintf(msg.str, sizeof(msg.str), "the received IKE_SA poposals "
+ snprintf(msg.str, sizeof(msg.str), "the received IKE_SA proposals "
"did not match: %#P", list);
break;
case ALERT_PROPOSAL_MISMATCH_CHILD:
msg.type = htonl(ERROR_NOTIFY_PROPOSAL_MISMATCH_CHILD);
list = va_arg(args, linked_list_t*);
- snprintf(msg.str, sizeof(msg.str), "the received CHILD_SA poposals "
+ snprintf(msg.str, sizeof(msg.str), "the received CHILD_SA proposals "
"did not match: %#P", list);
break;
case ALERT_TS_MISMATCH:
@@ -153,14 +153,14 @@ METHOD(listener_t, alert, bool,
msg.type = htonl(ERROR_NOTIFY_CERT_EXPIRED);
cert = va_arg(args, certificate_t*);
cert->get_validity(cert, NULL, &not_before, &not_after);
- snprintf(msg.str, sizeof(msg.str), "certificiate expired: '%Y' "
+ snprintf(msg.str, sizeof(msg.str), "certificate expired: '%Y' "
"(valid from %T to %T)", cert->get_subject(cert),
&not_before, TRUE, &not_after, TRUE);
break;
case ALERT_CERT_REVOKED:
msg.type = htonl(ERROR_NOTIFY_CERT_REVOKED);
cert = va_arg(args, certificate_t*);
- snprintf(msg.str, sizeof(msg.str), "certificiate revoked: '%Y'",
+ snprintf(msg.str, sizeof(msg.str), "certificate revoked: '%Y'",
cert->get_subject(cert));
break;
case ALERT_CERT_NO_ISSUER:
diff --git a/src/libcharon/plugins/ha/ha_ctl.c b/src/libcharon/plugins/ha/ha_ctl.c
index a95499742..54302e852 100644
--- a/src/libcharon/plugins/ha/ha_ctl.c
+++ b/src/libcharon/plugins/ha/ha_ctl.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -51,6 +52,41 @@ struct private_ha_ctl_t {
};
/**
+ * Change the permissions of the control FIFO, returns TRUE on success
+ */
+static bool change_fifo_permissions()
+{
+ if (chown(HA_FIFO, lib->caps->get_uid(lib->caps),
+ lib->caps->get_gid(lib->caps)) != 0)
+ {
+ DBG1(DBG_CFG, "changing HA FIFO permissions failed: %s",
+ strerror(errno));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Deletes and creates the control FIFO, returns TRUE on success
+ */
+static bool recreate_fifo()
+{
+ mode_t old;
+ bool success = TRUE;
+
+ unlink(HA_FIFO);
+ old = umask(S_IRWXO);
+ if (mkfifo(HA_FIFO, S_IRUSR | S_IWUSR) != 0)
+ {
+ DBG1(DBG_CFG, "creating HA FIFO %s failed: %s", HA_FIFO,
+ strerror(errno));
+ success = FALSE;
+ }
+ umask(old);
+ return success && change_fifo_permissions();
+}
+
+/**
* FIFO dispatching function
*/
static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
@@ -59,13 +95,26 @@ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
bool oldstate;
char buf[8];
u_int segment;
+ struct stat sb;
oldstate = thread_cancelability(TRUE);
fifo = open(HA_FIFO, O_RDONLY);
thread_cancelability(oldstate);
- if (fifo == -1)
+ if (fifo == -1 || fstat(fifo, &sb) != 0 || !S_ISFIFO(sb.st_mode))
{
- DBG1(DBG_CFG, "opening HA fifo failed: %s", strerror(errno));
+ if (fifo == -1 && errno != ENOENT)
+ {
+ DBG1(DBG_CFG, "opening HA FIFO failed: %s", strerror(errno));
+ }
+ else
+ {
+ DBG1(DBG_CFG, "%s is not a FIFO, recreate it", HA_FIFO);
+ recreate_fifo();
+ }
+ if (fifo != -1)
+ {
+ close(fifo);
+ }
sleep(1);
return JOB_REQUEUE_FAIR;
}
@@ -100,6 +149,7 @@ static job_requeue_t dispatch_fifo(private_ha_ctl_t *this)
METHOD(ha_ctl_t, destroy, void,
private_ha_ctl_t *this)
{
+ unlink(HA_FIFO);
free(this);
}
@@ -109,7 +159,7 @@ METHOD(ha_ctl_t, destroy, void,
ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache)
{
private_ha_ctl_t *this;
- mode_t old;
+ struct stat sb;
INIT(this,
.public = {
@@ -119,20 +169,30 @@ ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache)
.cache = cache,
);
- if (access(HA_FIFO, R_OK|W_OK) != 0)
+ if (stat(HA_FIFO, &sb) == 0)
{
- old = umask(S_IRWXO);
- if (mkfifo(HA_FIFO, S_IRUSR | S_IWUSR) != 0)
+ if (!S_ISFIFO(sb.st_mode))
{
- DBG1(DBG_CFG, "creating HA FIFO %s failed: %s",
- HA_FIFO, strerror(errno));
+ DBG1(DBG_CFG, "%s is not a FIFO, recreate it", HA_FIFO);
+ recreate_fifo();
+ }
+ else if (access(HA_FIFO, R_OK|W_OK) != 0)
+ {
+ DBG1(DBG_CFG, "accessing HA FIFO %s denied, recreate it", HA_FIFO);
+ recreate_fifo();
+ }
+ else
+ {
+ change_fifo_permissions();
}
- umask(old);
}
- if (chown(HA_FIFO, lib->caps->get_uid(lib->caps),
- lib->caps->get_gid(lib->caps)) != 0)
+ else if (errno == ENOENT)
{
- DBG1(DBG_CFG, "changing HA FIFO permissions failed: %s",
+ recreate_fifo();
+ }
+ else
+ {
+ DBG1(DBG_CFG, "accessing HA FIFO %s failed: %s", HA_FIFO,
strerror(errno));
}
@@ -141,4 +201,3 @@ ha_ctl_t *ha_ctl_create(ha_segments_t *segments, ha_cache_t *cache)
this, NULL, (callback_job_cancel_t)return_false, JOB_PRIO_CRITICAL));
return &this->public;
}
-
diff --git a/src/libcharon/plugins/ha/ha_dispatcher.c b/src/libcharon/plugins/ha/ha_dispatcher.c
index 31eeb934e..afa099309 100644
--- a/src/libcharon/plugins/ha/ha_dispatcher.c
+++ b/src/libcharon/plugins/ha/ha_dispatcher.c
@@ -135,6 +135,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty;
chunk_t secret = chunk_empty, old_skd = chunk_empty;
chunk_t dh_local = chunk_empty, dh_remote = chunk_empty, psk = chunk_empty;
+ host_t *other = NULL;
bool ok = FALSE;
enumerator = message->create_attribute_enumerator(message);
@@ -150,6 +151,9 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
old_sa = charon->ike_sa_manager->checkout(charon->ike_sa_manager,
value.ike_sa_id);
break;
+ case HA_REMOTE_ADDR:
+ other = value.host->clone(value.host);
+ break;
case HA_IKE_VERSION:
version = value.u8;
break;
@@ -252,6 +256,11 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
charon->ike_sa_manager, old_sa);
old_sa = NULL;
}
+ if (other)
+ {
+ ike_sa->set_other_host(ike_sa, other);
+ other = NULL;
+ }
ike_sa->set_state(ike_sa, IKE_CONNECTING);
ike_sa->set_proposal(ike_sa, proposal);
this->cache->cache(this->cache, ike_sa, message);
@@ -270,6 +279,7 @@ static void process_ike_add(private_ha_dispatcher_t *this, ha_message_t *message
{
charon->ike_sa_manager->checkin(charon->ike_sa_manager, old_sa);
}
+ DESTROY_IF(other);
DESTROY_IF(message);
}
@@ -637,7 +647,7 @@ static void process_child_add(private_ha_dispatcher_t *this,
u_int32_t inbound_spi = 0, outbound_spi = 0;
u_int16_t inbound_cpi = 0, outbound_cpi = 0;
u_int8_t mode = MODE_TUNNEL, ipcomp = 0;
- u_int16_t encr = ENCR_UNDEFINED, integ = AUTH_UNDEFINED, len = 0;
+ u_int16_t encr = 0, integ = 0, len = 0;
u_int16_t esn = NO_EXT_SEQ_NUMBERS;
u_int seg_i, seg_o;
chunk_t nonce_i = chunk_empty, nonce_r = chunk_empty, secret = chunk_empty;
diff --git a/src/libcharon/plugins/ha/ha_ike.c b/src/libcharon/plugins/ha/ha_ike.c
index 6b4b53c9c..7492dd06e 100644
--- a/src/libcharon/plugins/ha/ha_ike.c
+++ b/src/libcharon/plugins/ha/ha_ike.c
@@ -138,6 +138,7 @@ METHOD(listener_t, ike_keys, bool,
m->add_attribute(m, HA_PSK, shared->get_key(shared));
}
}
+ m->add_attribute(m, HA_REMOTE_ADDR, ike_sa->get_other_host(ike_sa));
this->socket->push(this->socket, m);
this->cache->cache(this->cache, ike_sa, m);
diff --git a/src/libcharon/plugins/ha/ha_kernel.c b/src/libcharon/plugins/ha/ha_kernel.c
index eed89e0bf..bd43dc351 100644
--- a/src/libcharon/plugins/ha/ha_kernel.c
+++ b/src/libcharon/plugins/ha/ha_kernel.c
@@ -36,6 +36,8 @@ typedef enum {
JHASH_LOOKUP2,
/* new variant, http://burtleburtle.net/bob/c/lookup3.c, since 2.6.37 */
JHASH_LOOKUP3,
+ /* variant with different init values, since 4.1 */
+ JHASH_LOOKUP3_1,
} jhash_version_t;
typedef struct private_ha_kernel_t private_ha_kernel_t;
@@ -88,8 +90,15 @@ static jhash_version_t get_jhash_version()
}
/* FALL */
case 2:
- DBG1(DBG_CFG, "detected Linux %d.%d, using new jhash", a, b);
- return JHASH_LOOKUP3;
+ if (a < 4 || (a == 4 && b == 0))
+ {
+ DBG1(DBG_CFG, "detected Linux %d.%d, using new jhash",
+ a, b);
+ return JHASH_LOOKUP3;
+ }
+ DBG1(DBG_CFG, "detected Linux %d.%d, using new jhash with "
+ "updated init values", a, b);
+ return JHASH_LOOKUP3_1;
default:
break;
}
@@ -126,6 +135,14 @@ static u_int32_t jhash(jhash_version_t version, u_int32_t a, u_int32_t b)
b -= c; b -= a; b ^= (a << 10);
c -= a; c -= b; c ^= (b >> 15);
break;
+ case JHASH_LOOKUP3_1:
+ /* changed with 4.1: # of 32-bit words shifted by 2 and c is
+ * initialized. we only use the two word variant with SPIs, so it's
+ * unlikely that b is 0 in that case */
+ c += ((b ? 2 : 1) << 2) + 0xdeadbeef;
+ a += ((b ? 2 : 1) << 2);
+ b += ((b ? 2 : 1) << 2);
+ /* FALL */
case JHASH_LOOKUP3:
a += 0xdeadbeef;
b += 0xdeadbeef;
diff --git a/src/libcharon/plugins/load_tester/load_tester.c b/src/libcharon/plugins/load_tester/load_tester.c
index b7b971ee8..f5a998ecc 100644
--- a/src/libcharon/plugins/load_tester/load_tester.c
+++ b/src/libcharon/plugins/load_tester/load_tester.c
@@ -21,6 +21,7 @@
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <errno.h>
/**
diff --git a/src/libcharon/plugins/load_tester/load_tester_control.c b/src/libcharon/plugins/load_tester/load_tester_control.c
index 5f089f5db..24076d443 100644
--- a/src/libcharon/plugins/load_tester/load_tester_control.c
+++ b/src/libcharon/plugins/load_tester/load_tester_control.c
@@ -239,7 +239,7 @@ static bool on_accept(private_load_tester_control_t *this, stream_t *io)
switch (charon->controller->initiate(charon->controller,
peer_cfg, child_cfg->get_ref(child_cfg),
- (void*)initiate_cb, listener, 0))
+ (void*)initiate_cb, listener, 0, FALSE))
{
case NEED_MORE:
/* Callback returns FALSE once it got track of this IKE_SA.
diff --git a/src/libcharon/plugins/load_tester/load_tester_plugin.c b/src/libcharon/plugins/load_tester/load_tester_plugin.c
index e684f22ce..c7380b974 100644
--- a/src/libcharon/plugins/load_tester/load_tester_plugin.c
+++ b/src/libcharon/plugins/load_tester/load_tester_plugin.c
@@ -152,7 +152,7 @@ static job_requeue_t do_load_test(private_load_tester_plugin_t *this)
charon->controller->initiate(charon->controller,
peer_cfg, child_cfg->get_ref(child_cfg),
- NULL, NULL, 0);
+ NULL, NULL, 0, FALSE);
if (s)
{
sleep(s);
diff --git a/src/libcharon/plugins/medcli/medcli_config.c b/src/libcharon/plugins/medcli/medcli_config.c
index 1fb57b928..25b138387 100644
--- a/src/libcharon/plugins/medcli/medcli_config.c
+++ b/src/libcharon/plugins/medcli/medcli_config.c
@@ -314,7 +314,7 @@ static job_requeue_t initiate_config(peer_cfg_t *peer_cfg)
peer_cfg->get_ref(peer_cfg);
enumerator->destroy(enumerator);
charon->controller->initiate(charon->controller,
- peer_cfg, child_cfg, NULL, NULL, 0);
+ peer_cfg, child_cfg, NULL, NULL, 0, FALSE);
}
else
{
diff --git a/src/libcharon/plugins/osx_attr/osx_attr_handler.c b/src/libcharon/plugins/osx_attr/osx_attr_handler.c
index d974b57ce..6baf76d35 100644
--- a/src/libcharon/plugins/osx_attr/osx_attr_handler.c
+++ b/src/libcharon/plugins/osx_attr/osx_attr_handler.c
@@ -31,6 +31,16 @@ struct private_osx_attr_handler_t {
* Public interface
*/
osx_attr_handler_t public;
+
+ /**
+ * Backup of original DNS servers, before we mess with it
+ */
+ CFMutableArrayRef original;
+
+ /**
+ * Append DNS servers to existing entries, instead of replacing
+ */
+ bool append;
};
/**
@@ -110,7 +120,8 @@ static CFMutableArrayRef get_array_from_dict(CFDictionaryRef dict,
/**
* Add/Remove a DNS server to the configuration
*/
-static bool manage_dns(int family, chunk_t data, bool add)
+static bool manage_dns(private_osx_attr_handler_t *this,
+ int family, chunk_t data, bool add)
{
SCDynamicStoreRef store;
CFStringRef path, dns;
@@ -138,6 +149,11 @@ static bool manage_dns(int family, chunk_t data, bool add)
dns = CFStringCreateWithCString(NULL, buf, kCFStringEncodingUTF8);
if (add)
{
+ if (!this->append && !this->original)
+ { /* backup orignal config, start with empty set */
+ this->original = arr;
+ arr = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
+ }
DBG1(DBG_CFG, "installing %s as DNS server", buf);
CFArrayInsertValueAtIndex(arr, 0, dns);
}
@@ -150,6 +166,12 @@ static bool manage_dns(int family, chunk_t data, bool add)
DBG1(DBG_CFG, "removing %s from DNS servers (%d)", buf, i);
CFArrayRemoveValueAtIndex(arr, i);
}
+ if (!this->append && this->original && CFArrayGetCount(arr) == 0)
+ { /* restore original config */
+ CFRelease(arr);
+ arr = this->original;
+ this->original = NULL;
+ }
}
CFRelease(dns);
CFDictionarySetValue(dict, CFSTR("ServerAddresses"), arr);
@@ -175,7 +197,7 @@ METHOD(attribute_handler_t, handle, bool,
switch (type)
{
case INTERNAL_IP4_DNS:
- return manage_dns(AF_INET, data, TRUE);
+ return manage_dns(this, AF_INET, data, TRUE);
default:
return FALSE;
}
@@ -188,7 +210,7 @@ METHOD(attribute_handler_t, release, void,
switch (type)
{
case INTERNAL_IP4_DNS:
- manage_dns(AF_INET, data, FALSE);
+ manage_dns(this, AF_INET, data, FALSE);
break;
default:
break;
@@ -240,6 +262,8 @@ osx_attr_handler_t *osx_attr_handler_create()
},
.destroy = _destroy,
},
+ .append = lib->settings->get_bool(lib->settings,
+ "%s.plugins.osx-attr.append", TRUE, lib->ns),
);
return &this->public;
diff --git a/src/libcharon/plugins/smp/smp.c b/src/libcharon/plugins/smp/smp.c
index 04bf382ed..2aa061fd2 100644
--- a/src/libcharon/plugins/smp/smp.c
+++ b/src/libcharon/plugins/smp/smp.c
@@ -488,7 +488,7 @@ static void request_control_initiate(xmlTextReaderPtr reader,
{
status = charon->controller->initiate(charon->controller,
peer, child, (controller_cb_t)xml_callback,
- writer, 0);
+ writer, 0, FALSE);
}
else
{
diff --git a/src/libcharon/plugins/sql/sql_config.c b/src/libcharon/plugins/sql/sql_config.c
index c47c7c0f8..ce24d180a 100644
--- a/src/libcharon/plugins/sql/sql_config.c
+++ b/src/libcharon/plugins/sql/sql_config.c
@@ -324,6 +324,14 @@ static peer_cfg_t *get_peer_cfg_by_id(private_sql_config_t *this, int id)
}
/**
+ * Check if the two IDs match (the first one is optional)
+ */
+static inline bool id_matches(identification_t *id, identification_t *sql_id)
+{
+ return !id || id->matches(id, sql_id) || sql_id->matches(sql_id, id);
+}
+
+/**
* Build a peer config from an SQL query
*/
static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
@@ -352,8 +360,7 @@ static peer_cfg_t *build_peer_cfg(private_sql_config_t *this, enumerator_t *e,
local_id = identification_create_from_encoding(l_type, l_data);
remote_id = identification_create_from_encoding(r_type, r_data);
- if ((me && !me->matches(me, local_id)) ||
- (other && !other->matches(other, remote_id)))
+ if (!id_matches(me, local_id) || !id_matches(other, remote_id))
{
local_id->destroy(local_id);
remote_id->destroy(remote_id);
diff --git a/src/libcharon/plugins/sql/sql_logger.c b/src/libcharon/plugins/sql/sql_logger.c
index 9a7a6e0ff..0fa06eac5 100644
--- a/src/libcharon/plugins/sql/sql_logger.c
+++ b/src/libcharon/plugins/sql/sql_logger.c
@@ -120,6 +120,7 @@ METHOD(logger_t, get_level, level_t,
METHOD(sql_logger_t, destroy, void,
private_sql_logger_t *this)
{
+ this->recursive->destroy(this->recursive);
free(this);
}
diff --git a/src/libcharon/plugins/stroke/stroke_ca.c b/src/libcharon/plugins/stroke/stroke_ca.c
index b470b81c6..13ed41e0e 100644
--- a/src/libcharon/plugins/stroke/stroke_ca.c
+++ b/src/libcharon/plugins/stroke/stroke_ca.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2015 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -24,6 +24,13 @@
#include <daemon.h>
typedef struct private_stroke_ca_t private_stroke_ca_t;
+typedef struct ca_section_t ca_section_t;
+typedef struct ca_cert_t ca_cert_t;
+
+/**
+ * Provided by stroke_cred.c
+ */
+certificate_t *stroke_load_ca_cert(char *filename);
/**
* private data of stroke_ca
@@ -41,17 +48,16 @@ struct private_stroke_ca_t {
rwlock_t *lock;
/**
- * list of starters CA sections and its certificates (ca_section_t)
+ * list of CA sections and their certificates (ca_section_t)
*/
linked_list_t *sections;
/**
- * stroke credentials, stores our CA certificates
+ * list of all loaded CA certificates (ca_cert_t)
*/
- stroke_cred_t *cred;
+ linked_list_t *certs;
};
-typedef struct ca_section_t ca_section_t;
/**
* loaded ipsec.conf CA sections
@@ -64,7 +70,12 @@ struct ca_section_t {
char *name;
/**
- * reference to cert in trusted_credential_t
+ * path/name of the certificate
+ */
+ char *path;
+
+ /**
+ * reference to cert
*/
certificate_t *cert;
@@ -90,16 +101,37 @@ struct ca_section_t {
};
/**
+ * loaded CA certificate
+ */
+struct ca_cert_t {
+
+ /**
+ * reference to cert
+ */
+ certificate_t *cert;
+
+ /**
+ * The number of CA sections referring to this certificate
+ */
+ u_int count;
+
+ /**
+ * TRUE if this certificate was automatically loaded
+ */
+ bool automatic;
+};
+
+/**
* create a new CA section
*/
-static ca_section_t *ca_section_create(char *name, certificate_t *cert)
+static ca_section_t *ca_section_create(char *name, char *path)
{
ca_section_t *ca = malloc_thing(ca_section_t);
ca->name = strdup(name);
+ ca->path = strdup(path);
ca->crl = linked_list_create();
ca->ocsp = linked_list_create();
- ca->cert = cert;
ca->hashes = linked_list_create();
ca->certuribase = NULL;
return ca;
@@ -115,11 +147,21 @@ static void ca_section_destroy(ca_section_t *this)
this->hashes->destroy_offset(this->hashes, offsetof(identification_t, destroy));
this->cert->destroy(this->cert);
free(this->certuribase);
+ free(this->path);
free(this->name);
free(this);
}
/**
+ * Destroy a ca cert entry
+ */
+static void ca_cert_destroy(ca_cert_t *this)
+{
+ this->cert->destroy(this->cert);
+ free(this);
+}
+
+/**
* Data for the certificate enumerator
*/
typedef struct {
@@ -141,7 +183,7 @@ static void cert_data_destroy(cert_data_t *data)
/**
* filter function for certs enumerator
*/
-static bool certs_filter(cert_data_t *data, ca_section_t **in,
+static bool certs_filter(cert_data_t *data, ca_cert_t **in,
certificate_t **out)
{
public_key_t *public;
@@ -192,7 +234,7 @@ METHOD(credential_set_t, create_cert_enumerator, enumerator_t*,
);
this->lock->read_lock(this->lock);
- enumerator = this->sections->create_enumerator(this->sections);
+ enumerator = this->certs->create_enumerator(this->certs);
return enumerator_create_filter(enumerator, (void*)certs_filter, data,
(void*)cert_data_destroy);
}
@@ -312,6 +354,81 @@ METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*,
data, (void*)cdp_data_destroy);
}
+/**
+ * Compare the given certificate to the ca_cert_t items in the list
+ */
+static bool match_cert(ca_cert_t *item, certificate_t *cert)
+{
+ return cert->equals(cert, item->cert);
+}
+
+/**
+ * Match automatically added certificates and remove/destroy them if they are
+ * not referenced by CA sections.
+ */
+static bool remove_auto_certs(ca_cert_t *item, void *not_used)
+{
+ if (item->automatic)
+ {
+ item->automatic = FALSE;
+ if (!item->count)
+ {
+ ca_cert_destroy(item);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Find the given certificate that was referenced by a section and remove it
+ * unless it was also loaded automatically or is used by other CA sections.
+ */
+static bool remove_cert(ca_cert_t *item, certificate_t *cert)
+{
+ if (item->count && cert->equals(cert, item->cert))
+ {
+ if (--item->count == 0 && !item->automatic)
+ {
+ ca_cert_destroy(item);
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/**
+ * Adds a certificate to the certificate store
+ */
+static certificate_t *add_cert_internal(private_stroke_ca_t *this,
+ certificate_t *cert, bool automatic)
+{
+ ca_cert_t *found;
+
+ if (this->certs->find_first(this->certs, (linked_list_match_t)match_cert,
+ (void**)&found, cert) == SUCCESS)
+ {
+ cert->destroy(cert);
+ cert = found->cert->get_ref(found->cert);
+ }
+ else
+ {
+ INIT(found,
+ .cert = cert->get_ref(cert)
+ );
+ this->certs->insert_first(this->certs, found);
+ }
+ if (automatic)
+ {
+ found->automatic = TRUE;
+ }
+ else
+ {
+ found->count++;
+ }
+ return cert;
+}
+
METHOD(stroke_ca_t, add, void,
private_stroke_ca_t *this, stroke_msg_t *msg)
{
@@ -323,10 +440,10 @@ METHOD(stroke_ca_t, add, void,
DBG1(DBG_CFG, "missing cacert parameter");
return;
}
- cert = this->cred->load_ca(this->cred, msg->add_ca.cacert);
+ cert = stroke_load_ca_cert(msg->add_ca.cacert);
if (cert)
{
- ca = ca_section_create(msg->add_ca.name, cert);
+ ca = ca_section_create(msg->add_ca.name, msg->add_ca.cacert);
if (msg->add_ca.crluri)
{
ca->crl->insert_last(ca->crl, strdup(msg->add_ca.crluri));
@@ -348,6 +465,7 @@ METHOD(stroke_ca_t, add, void,
ca->certuribase = strdup(msg->add_ca.certuribase);
}
this->lock->write_lock(this->lock);
+ ca->cert = add_cert_internal(this, cert, FALSE);
this->sections->insert_last(this->sections, ca);
this->lock->unlock(this->lock);
DBG1(DBG_CFG, "added ca '%s'", msg->add_ca.name);
@@ -372,8 +490,12 @@ METHOD(stroke_ca_t, del, void,
ca = NULL;
}
enumerator->destroy(enumerator);
+ if (ca)
+ {
+ this->certs->remove(this->certs, ca->cert, (void*)remove_cert);
+ }
this->lock->unlock(this->lock);
- if (ca == NULL)
+ if (!ca)
{
DBG1(DBG_CFG, "no ca named '%s' found\n", msg->del_ca.name);
return;
@@ -383,6 +505,88 @@ METHOD(stroke_ca_t, del, void,
lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
}
+METHOD(stroke_ca_t, get_cert_ref, certificate_t*,
+ private_stroke_ca_t *this, certificate_t *cert)
+{
+ ca_cert_t *found;
+
+ this->lock->read_lock(this->lock);
+ if (this->certs->find_first(this->certs, (linked_list_match_t)match_cert,
+ (void**)&found, cert) == SUCCESS)
+ {
+ cert->destroy(cert);
+ cert = found->cert->get_ref(found->cert);
+ }
+ this->lock->unlock(this->lock);
+ return cert;
+}
+
+METHOD(stroke_ca_t, reload_certs, void,
+ private_stroke_ca_t *this)
+{
+ enumerator_t *enumerator;
+ certificate_t *cert;
+ ca_section_t *ca;
+ certificate_type_t type = CERT_X509;
+
+ /* holding the write lock while loading/parsing certificates is not optimal,
+ * however, there usually are not that many ca sections configured */
+ this->lock->write_lock(this->lock);
+ if (this->sections->get_count(this->sections))
+ {
+ DBG1(DBG_CFG, "rereading ca certificates in ca sections");
+ }
+ enumerator = this->sections->create_enumerator(this->sections);
+ while (enumerator->enumerate(enumerator, &ca))
+ {
+ cert = stroke_load_ca_cert(ca->path);
+ if (cert)
+ {
+ if (cert->equals(cert, ca->cert))
+ {
+ cert->destroy(cert);
+ }
+ else
+ {
+ this->certs->remove(this->certs, ca->cert, (void*)remove_cert);
+ ca->cert->destroy(ca->cert);
+ ca->cert = add_cert_internal(this, cert, FALSE);
+ }
+ }
+ else
+ {
+ DBG1(DBG_CFG, "failed to reload certificate '%s', removing ca '%s'",
+ ca->path, ca->name);
+ this->sections->remove_at(this->sections, enumerator);
+ this->certs->remove(this->certs, ca->cert, (void*)remove_cert);
+ ca_section_destroy(ca);
+ type = CERT_ANY;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+ lib->credmgr->flush_cache(lib->credmgr, type);
+}
+
+METHOD(stroke_ca_t, replace_certs, void,
+ private_stroke_ca_t *this, mem_cred_t *certs)
+{
+ enumerator_t *enumerator;
+ certificate_t *cert;
+
+ enumerator = certs->set.create_cert_enumerator(&certs->set, CERT_X509,
+ KEY_ANY, NULL, TRUE);
+ this->lock->write_lock(this->lock);
+ this->certs->remove(this->certs, NULL, (void*)remove_auto_certs);
+ while (enumerator->enumerate(enumerator, &cert))
+ {
+ cert = add_cert_internal(this, cert->get_ref(cert), TRUE);
+ cert->destroy(cert);
+ }
+ this->lock->unlock(this->lock);
+ enumerator->destroy(enumerator);
+ lib->credmgr->flush_cache(lib->credmgr, CERT_X509);
+}
/**
* list crl or ocsp URIs
*/
@@ -501,6 +705,7 @@ METHOD(stroke_ca_t, destroy, void,
private_stroke_ca_t *this)
{
this->sections->destroy_function(this->sections, (void*)ca_section_destroy);
+ this->certs->destroy_function(this->certs, (void*)ca_cert_destroy);
this->lock->destroy(this->lock);
free(this);
}
@@ -508,7 +713,7 @@ METHOD(stroke_ca_t, destroy, void,
/*
* see header file
*/
-stroke_ca_t *stroke_ca_create(stroke_cred_t *cred)
+stroke_ca_t *stroke_ca_create()
{
private_stroke_ca_t *this;
@@ -524,12 +729,15 @@ stroke_ca_t *stroke_ca_create(stroke_cred_t *cred)
.add = _add,
.del = _del,
.list = _list,
+ .get_cert_ref = _get_cert_ref,
+ .reload_certs = _reload_certs,
+ .replace_certs = _replace_certs,
.check_for_hash_and_url = _check_for_hash_and_url,
.destroy = _destroy,
},
.sections = linked_list_create(),
+ .certs = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
- .cred = cred,
);
return &this->public;
diff --git a/src/libcharon/plugins/stroke/stroke_ca.h b/src/libcharon/plugins/stroke/stroke_ca.h
index 21af912ea..2740006e2 100644
--- a/src/libcharon/plugins/stroke/stroke_ca.h
+++ b/src/libcharon/plugins/stroke/stroke_ca.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Tobias Brunner
+ * Copyright (C) 2008-2015 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -23,8 +23,7 @@
#define STROKE_CA_H_
#include <stroke_msg.h>
-
-#include "stroke_cred.h"
+#include <credentials/sets/mem_cred.h>
typedef struct stroke_ca_t stroke_ca_t;
@@ -67,6 +66,29 @@ struct stroke_ca_t {
void (*check_for_hash_and_url)(stroke_ca_t *this, certificate_t* cert);
/**
+ * Get a reference to a CA certificate if it is already stored,
+ * otherwise returns the same certificate.
+ *
+ * @param cert certificate to check
+ * @return reference to stored CA certifiate, or original
+ */
+ certificate_t *(*get_cert_ref)(stroke_ca_t *this, certificate_t *cert);
+
+ /**
+ * Reload CA certificates referenced in CA sections. Flushes the certificate
+ * cache.
+ */
+ void (*reload_certs)(stroke_ca_t *this);
+
+ /**
+ * Replace automatically loaded CA certificates. Flushes the certificate
+ * cache.
+ *
+ * @param certs credential set to take certificates from (not modified)
+ */
+ void (*replace_certs)(stroke_ca_t *this, mem_cred_t *certs);
+
+ /**
* Destroy a stroke_ca instance.
*/
void (*destroy)(stroke_ca_t *this);
@@ -75,6 +97,6 @@ struct stroke_ca_t {
/**
* Create a stroke_ca instance.
*/
-stroke_ca_t *stroke_ca_create(stroke_cred_t *cred);
+stroke_ca_t *stroke_ca_create();
#endif /** STROKE_CA_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_config.c b/src/libcharon/plugins/stroke/stroke_config.c
index 55ec7cdc9..f71719458 100644
--- a/src/libcharon/plugins/stroke/stroke_config.c
+++ b/src/libcharon/plugins/stroke/stroke_config.c
@@ -184,19 +184,16 @@ static void add_proposals(private_stroke_config_t *this, char *string,
}
/**
- * Build an IKE config from a stroke message
+ * Check if any addresses in the given string are local
*/
-static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg)
+static bool is_local(char *address, bool any_allowed)
{
enumerator_t *enumerator;
- stroke_end_t tmp_end;
- ike_cfg_t *ike_cfg;
host_t *host;
- u_int16_t ikeport;
- char me[256], other[256], *token;
- bool swapped = FALSE;;
+ char *token;
+ bool found = FALSE;
- enumerator = enumerator_create_token(msg->add_conn.other.address, ",", " ");
+ enumerator = enumerator_create_token(address, ",", " ");
while (enumerator->enumerate(enumerator, &token))
{
if (!strchr(token, '/'))
@@ -207,40 +204,60 @@ static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg
if (hydra->kernel_interface->get_interface(
hydra->kernel_interface, host, NULL))
{
- DBG2(DBG_CFG, "left is other host, swapping ends");
- tmp_end = msg->add_conn.me;
- msg->add_conn.me = msg->add_conn.other;
- msg->add_conn.other = tmp_end;
- swapped = TRUE;
+ found = TRUE;
+ }
+ else if (any_allowed && host->is_anyaddr(host))
+ {
+ found = TRUE;
}
host->destroy(host);
+ if (found)
+ {
+ break;
+ }
}
}
}
enumerator->destroy(enumerator);
+ return found;
+}
- if (!swapped)
+/**
+ * Swap ends if indicated by left|right
+ */
+static void swap_ends(stroke_msg_t *msg)
+{
+ if (!lib->settings->get_bool(lib->settings, "%s.plugins.stroke.allow_swap",
+ TRUE, lib->ns))
{
- enumerator = enumerator_create_token(msg->add_conn.me.address, ",", " ");
- while (enumerator->enumerate(enumerator, &token))
- {
- if (!strchr(token, '/'))
- {
- host = host_create_from_dns(token, 0, 0);
- if (host)
- {
- if (!hydra->kernel_interface->get_interface(
- hydra->kernel_interface, host, NULL))
- {
- DBG1(DBG_CFG, "left nor right host is our side, "
- "assuming left=local");
- }
- host->destroy(host);
- }
- }
- }
- enumerator->destroy(enumerator);
+ return;
+ }
+
+ if (is_local(msg->add_conn.other.address, FALSE))
+ {
+ stroke_end_t tmp_end;
+
+ DBG2(DBG_CFG, "left is other host, swapping ends");
+ tmp_end = msg->add_conn.me;
+ msg->add_conn.me = msg->add_conn.other;
+ msg->add_conn.other = tmp_end;
+ }
+ else if (!is_local(msg->add_conn.me.address, TRUE))
+ {
+ DBG1(DBG_CFG, "left nor right host is our side, assuming left=local");
}
+}
+
+/**
+ * Build an IKE config from a stroke message
+ */
+static ike_cfg_t *build_ike_cfg(private_stroke_config_t *this, stroke_msg_t *msg)
+{
+ ike_cfg_t *ike_cfg;
+ u_int16_t ikeport;
+ char me[256], other[256];
+
+ swap_ends(msg);
if (msg->add_conn.me.allow_any)
{
diff --git a/src/libcharon/plugins/stroke/stroke_control.c b/src/libcharon/plugins/stroke/stroke_control.c
index 0084fbf93..0125d17c6 100644
--- a/src/libcharon/plugins/stroke/stroke_control.c
+++ b/src/libcharon/plugins/stroke/stroke_control.c
@@ -109,7 +109,7 @@ static void charon_initiate(private_stroke_control_t *this, peer_cfg_t *peer_cfg
if (msg->output_verbosity < 0)
{
charon->controller->initiate(charon->controller, peer_cfg, child_cfg,
- NULL, NULL, 0);
+ NULL, NULL, 0, FALSE);
}
else
{
@@ -118,7 +118,7 @@ static void charon_initiate(private_stroke_control_t *this, peer_cfg_t *peer_cfg
status = charon->controller->initiate(charon->controller,
peer_cfg, child_cfg, (controller_cb_t)stroke_log,
- &info, this->timeout);
+ &info, this->timeout, FALSE);
switch (status)
{
case SUCCESS:
diff --git a/src/libcharon/plugins/stroke/stroke_cred.c b/src/libcharon/plugins/stroke/stroke_cred.c
index 5e423f1de..42928882a 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.c
+++ b/src/libcharon/plugins/stroke/stroke_cred.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2013 Tobias Brunner
+ * Copyright (C) 2008-2015 Tobias Brunner
* Copyright (C) 2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -75,11 +75,6 @@ struct private_stroke_cred_t {
mem_cred_t *creds;
/**
- * CA certificates
- */
- mem_cred_t *cacerts;
-
- /**
* Attribute Authority certificates
*/
mem_cred_t *aacerts;
@@ -94,6 +89,11 @@ struct private_stroke_cred_t {
* cache CRLs to disk?
*/
bool cachecrl;
+
+ /**
+ * CA certificate store
+ */
+ stroke_ca_t *ca;
};
/** Length of smartcard specifier parts (module, keyid) */
@@ -182,70 +182,6 @@ static certificate_t *load_from_smartcard(smartcard_format_t format,
return cred;
}
-METHOD(stroke_cred_t, load_ca, certificate_t*,
- private_stroke_cred_t *this, char *filename)
-{
- certificate_t *cert = NULL;
- char path[PATH_MAX];
-
- if (strpfx(filename, "%smartcard"))
- {
- smartcard_format_t format;
- char module[SC_PART_LEN], keyid[SC_PART_LEN];
- u_int slot;
-
- format = parse_smartcard(filename, &slot, module, keyid);
- if (format != SC_FORMAT_INVALID)
- {
- cert = (certificate_t*)load_from_smartcard(format,
- slot, module, keyid, CRED_CERTIFICATE, CERT_X509);
- }
- }
- else
- {
- if (*filename == '/')
- {
- snprintf(path, sizeof(path), "%s", filename);
- }
- else
- {
- snprintf(path, sizeof(path), "%s/%s", CA_CERTIFICATE_DIR, filename);
- }
-
- if (this->force_ca_cert)
- { /* we treat this certificate as a CA certificate even if it has no
- * CA basic constraint */
- cert = lib->creds->create(lib->creds,
- CRED_CERTIFICATE, CERT_X509,
- BUILD_FROM_FILE, path, BUILD_X509_FLAG, X509_CA,
- BUILD_END);
- }
- else
- {
- cert = lib->creds->create(lib->creds,
- CRED_CERTIFICATE, CERT_X509,
- BUILD_FROM_FILE, path,
- BUILD_END);
- }
- }
- if (cert)
- {
- x509_t *x509 = (x509_t*)cert;
-
- if (!(x509->get_flags(x509) & X509_CA))
- {
- DBG1(DBG_CFG, " ca certificate \"%Y\" misses ca basic constraint, "
- "discarded", cert->get_subject(cert));
- cert->destroy(cert);
- return NULL;
- }
- DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'",
- cert->get_subject(cert), filename);
- return this->creds->get_cert_ref(this->creds, cert);
- }
- return NULL;
-}
-
METHOD(stroke_cred_t, load_peer, certificate_t*,
private_stroke_cred_t *this, char *filename)
{
@@ -384,22 +320,52 @@ METHOD(stroke_cred_t, load_pubkey, certificate_t*,
}
/**
- * Load a CA certificate from disk
+ * Load a CA certificate, optionally force it to be one
*/
-static void load_x509_ca(private_stroke_cred_t *this, char *file)
+static certificate_t *load_ca_cert(char *filename, bool force_ca_cert)
{
- certificate_t *cert;
+ certificate_t *cert = NULL;
+ char path[PATH_MAX];
+
+ if (strpfx(filename, "%smartcard"))
+ {
+ smartcard_format_t format;
+ char module[SC_PART_LEN], keyid[SC_PART_LEN];
+ u_int slot;
- if (this->force_ca_cert)
- { /* treat certificate as CA cert even it has no CA basic constraint */
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_FROM_FILE, file,
- BUILD_X509_FLAG, X509_CA, BUILD_END);
+ format = parse_smartcard(filename, &slot, module, keyid);
+ if (format != SC_FORMAT_INVALID)
+ {
+ cert = (certificate_t*)load_from_smartcard(format,
+ slot, module, keyid, CRED_CERTIFICATE, CERT_X509);
+ }
}
else
{
- cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
- BUILD_FROM_FILE, file, BUILD_END);
+ if (*filename == '/')
+ {
+ snprintf(path, sizeof(path), "%s", filename);
+ }
+ else
+ {
+ snprintf(path, sizeof(path), "%s/%s", CA_CERTIFICATE_DIR, filename);
+ }
+
+ if (force_ca_cert)
+ { /* we treat this certificate as a CA certificate even if it has no
+ * CA basic constraint */
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, path, BUILD_X509_FLAG, X509_CA,
+ BUILD_END);
+ }
+ else
+ {
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, path,
+ BUILD_END);
+ }
}
if (cert)
{
@@ -410,13 +376,41 @@ static void load_x509_ca(private_stroke_cred_t *this, char *file)
DBG1(DBG_CFG, " ca certificate \"%Y\" lacks ca basic constraint, "
"discarded", cert->get_subject(cert));
cert->destroy(cert);
+ return NULL;
}
- else
- {
- DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'",
- cert->get_subject(cert), file);
- this->cacerts->add_cert(this->cacerts, TRUE, cert);
- }
+ DBG1(DBG_CFG, " loaded ca certificate \"%Y\" from '%s'",
+ cert->get_subject(cert), filename);
+ return cert;
+ }
+ return NULL;
+}
+
+/**
+ * Used by stroke_ca.c
+ */
+certificate_t *stroke_load_ca_cert(char *filename)
+{
+ bool force_ca_cert;
+
+ force_ca_cert = lib->settings->get_bool(lib->settings,
+ "%s.plugins.stroke.ignore_missing_ca_basic_constraint",
+ FALSE, lib->ns);
+ return load_ca_cert(filename, force_ca_cert);
+}
+
+/**
+ * Load a CA certificate from disk
+ */
+static void load_x509_ca(private_stroke_cred_t *this, char *file,
+ mem_cred_t *creds)
+{
+ certificate_t *cert;
+
+ cert = load_ca_cert(file, this->force_ca_cert);
+ if (cert)
+ {
+ cert = this->ca->get_cert_ref(this->ca, cert);
+ creds->add_cert(creds, TRUE, cert);
}
else
{
@@ -427,7 +421,8 @@ static void load_x509_ca(private_stroke_cred_t *this, char *file)
/**
* Load AA certificate with flags from disk
*/
-static void load_x509_aa(private_stroke_cred_t *this, char *file)
+static void load_x509_aa(private_stroke_cred_t *this,char *file,
+ mem_cred_t *creds)
{
certificate_t *cert;
@@ -438,7 +433,7 @@ static void load_x509_aa(private_stroke_cred_t *this, char *file)
{
DBG1(DBG_CFG, " loaded AA certificate \"%Y\" from '%s'",
cert->get_subject(cert), file);
- this->aacerts->add_cert(this->aacerts, TRUE, cert);
+ creds->add_cert(creds, TRUE, cert);
}
else
{
@@ -449,7 +444,8 @@ static void load_x509_aa(private_stroke_cred_t *this, char *file)
/**
* Load a certificate with flags from disk
*/
-static void load_x509(private_stroke_cred_t *this, char *file, x509_flag_t flag)
+static void load_x509(private_stroke_cred_t *this, char *file, x509_flag_t flag,
+ mem_cred_t *creds)
{
certificate_t *cert;
@@ -461,7 +457,7 @@ static void load_x509(private_stroke_cred_t *this, char *file, x509_flag_t flag)
{
DBG1(DBG_CFG, " loaded certificate \"%Y\" from '%s'",
cert->get_subject(cert), file);
- this->creds->add_cert(this->creds, TRUE, cert);
+ creds->add_cert(creds, TRUE, cert);
}
else
{
@@ -472,7 +468,8 @@ static void load_x509(private_stroke_cred_t *this, char *file, x509_flag_t flag)
/**
* Load a CRL from a file
*/
-static void load_x509_crl(private_stroke_cred_t *this, char *file)
+static void load_x509_crl(private_stroke_cred_t *this, char *file,
+ mem_cred_t *creds)
{
certificate_t *cert;
@@ -480,8 +477,8 @@ static void load_x509_crl(private_stroke_cred_t *this, char *file)
BUILD_FROM_FILE, file, BUILD_END);
if (cert)
{
- this->creds->add_crl(this->creds, (crl_t*)cert);
DBG1(DBG_CFG, " loaded crl from '%s'", file);
+ creds->add_crl(creds, (crl_t*)cert);
}
else
{
@@ -492,7 +489,8 @@ static void load_x509_crl(private_stroke_cred_t *this, char *file)
/**
* Load an attribute certificate from a file
*/
-static void load_x509_ac(private_stroke_cred_t *this, char *file)
+static void load_x509_ac(private_stroke_cred_t *this, char *file,
+ mem_cred_t *creds)
{
certificate_t *cert;
@@ -501,7 +499,7 @@ static void load_x509_ac(private_stroke_cred_t *this, char *file)
if (cert)
{
DBG1(DBG_CFG, " loaded attribute certificate from '%s'", file);
- this->creds->add_cert(this->creds, FALSE, cert);
+ creds->add_cert(creds, FALSE, cert);
}
else
{
@@ -513,7 +511,8 @@ static void load_x509_ac(private_stroke_cred_t *this, char *file)
* load trusted certificates from a directory
*/
static void load_certdir(private_stroke_cred_t *this, char *path,
- certificate_type_t type, x509_flag_t flag)
+ certificate_type_t type, x509_flag_t flag,
+ mem_cred_t *creds)
{
enumerator_t *enumerator;
struct stat st;
@@ -534,22 +533,22 @@ static void load_certdir(private_stroke_cred_t *this, char *path,
case CERT_X509:
if (flag & X509_CA)
{
- load_x509_ca(this, file);
+ load_x509_ca(this, file, creds);
}
else if (flag & X509_AA)
{
- load_x509_aa(this, file);
+ load_x509_aa(this, file, creds);
}
else
{
- load_x509(this, file, flag);
+ load_x509(this, file, flag, creds);
}
break;
case CERT_X509_CRL:
- load_x509_crl(this, file);
+ load_x509_crl(this, file, creds);
break;
case CERT_X509_AC:
- load_x509_ac(this, file);
+ load_x509_ac(this, file, creds);
break;
default:
break;
@@ -1348,30 +1347,38 @@ static void load_secrets(private_stroke_cred_t *this, mem_cred_t *secrets,
*/
static void load_certs(private_stroke_cred_t *this)
{
+ mem_cred_t *creds;
+
DBG1(DBG_CFG, "loading ca certificates from '%s'",
CA_CERTIFICATE_DIR);
- load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA);
+ creds = mem_cred_create();
+ load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA, creds);
+ this->ca->replace_certs(this->ca, creds);
+ creds->destroy(creds);
DBG1(DBG_CFG, "loading aa certificates from '%s'",
AA_CERTIFICATE_DIR);
- load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA);
+ load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA, this->aacerts);
DBG1(DBG_CFG, "loading ocsp signer certificates from '%s'",
OCSP_CERTIFICATE_DIR);
- load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509, X509_OCSP_SIGNER);
+ load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509, X509_OCSP_SIGNER,
+ this->creds);
DBG1(DBG_CFG, "loading attribute certificates from '%s'",
ATTR_CERTIFICATE_DIR);
- load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0);
+ load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0, this->creds);
DBG1(DBG_CFG, "loading crls from '%s'",
CRL_DIR);
- load_certdir(this, CRL_DIR, CERT_X509_CRL, 0);
+ load_certdir(this, CRL_DIR, CERT_X509_CRL, 0, this->creds);
}
METHOD(stroke_cred_t, reread, void,
private_stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt)
{
+ mem_cred_t *creds;
+
if (msg->reread.flags & REREAD_SECRETS)
{
DBG1(DBG_CFG, "rereading secrets");
@@ -1379,38 +1386,44 @@ METHOD(stroke_cred_t, reread, void,
}
if (msg->reread.flags & REREAD_CACERTS)
{
+ /* first reload certificates in ca sections, so we can refer to them */
+ this->ca->reload_certs(this->ca);
+
DBG1(DBG_CFG, "rereading ca certificates from '%s'",
CA_CERTIFICATE_DIR);
- this->cacerts->clear(this->cacerts);
+ creds = mem_cred_create();
+ load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA, creds);
+ this->ca->replace_certs(this->ca, creds);
+ creds->destroy(creds);
+ }
+ if (msg->reread.flags & REREAD_AACERTS)
+ {
+ DBG1(DBG_CFG, "rereading aa certificates from '%s'",
+ AA_CERTIFICATE_DIR);
+ creds = mem_cred_create();
+ load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA, creds);
+ this->aacerts->replace_certs(this->aacerts, creds, FALSE);
+ creds->destroy(creds);
lib->credmgr->flush_cache(lib->credmgr, CERT_X509);
- load_certdir(this, CA_CERTIFICATE_DIR, CERT_X509, X509_CA);
}
if (msg->reread.flags & REREAD_OCSPCERTS)
{
DBG1(DBG_CFG, "rereading ocsp signer certificates from '%s'",
OCSP_CERTIFICATE_DIR);
load_certdir(this, OCSP_CERTIFICATE_DIR, CERT_X509,
- X509_OCSP_SIGNER);
- }
- if (msg->reread.flags & REREAD_AACERTS)
- {
- DBG1(DBG_CFG, "rereading aa certificates from '%s'",
- AA_CERTIFICATE_DIR);
- this->aacerts->clear(this->aacerts);
- lib->credmgr->flush_cache(lib->credmgr, CERT_X509);
- load_certdir(this, AA_CERTIFICATE_DIR, CERT_X509, X509_AA);
+ X509_OCSP_SIGNER, this->creds);
}
if (msg->reread.flags & REREAD_ACERTS)
{
DBG1(DBG_CFG, "rereading attribute certificates from '%s'",
ATTR_CERTIFICATE_DIR);
- load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0);
+ load_certdir(this, ATTR_CERTIFICATE_DIR, CERT_X509_AC, 0, this->creds);
}
if (msg->reread.flags & REREAD_CRLS)
{
DBG1(DBG_CFG, "rereading crls from '%s'",
CRL_DIR);
- load_certdir(this, CRL_DIR, CERT_X509_CRL, 0);
+ load_certdir(this, CRL_DIR, CERT_X509_CRL, 0, this->creds);
}
}
@@ -1424,10 +1437,8 @@ METHOD(stroke_cred_t, destroy, void,
private_stroke_cred_t *this)
{
lib->credmgr->remove_set(lib->credmgr, &this->aacerts->set);
- lib->credmgr->remove_set(lib->credmgr, &this->cacerts->set);
lib->credmgr->remove_set(lib->credmgr, &this->creds->set);
this->aacerts->destroy(this->aacerts);
- this->cacerts->destroy(this->cacerts);
this->creds->destroy(this->creds);
free(this);
}
@@ -1435,7 +1446,7 @@ METHOD(stroke_cred_t, destroy, void,
/*
* see header file
*/
-stroke_cred_t *stroke_cred_create()
+stroke_cred_t *stroke_cred_create(stroke_ca_t *ca)
{
private_stroke_cred_t *this;
@@ -1449,7 +1460,6 @@ stroke_cred_t *stroke_cred_create()
.cache_cert = (void*)_cache_cert,
},
.reread = _reread,
- .load_ca = _load_ca,
.load_peer = _load_peer,
.load_pubkey = _load_pubkey,
.add_shared = _add_shared,
@@ -1460,12 +1470,11 @@ stroke_cred_t *stroke_cred_create()
"%s.plugins.stroke.secrets_file", SECRETS_FILE,
lib->ns),
.creds = mem_cred_create(),
- .cacerts = mem_cred_create(),
.aacerts = mem_cred_create(),
+ .ca = ca,
);
lib->credmgr->add_set(lib->credmgr, &this->creds->set);
- lib->credmgr->add_set(lib->credmgr, &this->cacerts->set);
lib->credmgr->add_set(lib->credmgr, &this->aacerts->set);
this->force_ca_cert = lib->settings->get_bool(lib->settings,
diff --git a/src/libcharon/plugins/stroke/stroke_cred.h b/src/libcharon/plugins/stroke/stroke_cred.h
index 9434629ef..33a0e3531 100644
--- a/src/libcharon/plugins/stroke/stroke_cred.h
+++ b/src/libcharon/plugins/stroke/stroke_cred.h
@@ -29,6 +29,8 @@
#include <credentials/certificates/certificate.h>
#include <collections/linked_list.h>
+#include "stroke_ca.h"
+
typedef struct stroke_cred_t stroke_cred_t;
/**
@@ -50,17 +52,6 @@ struct stroke_cred_t {
void (*reread)(stroke_cred_t *this, stroke_msg_t *msg, FILE *prompt);
/**
- * Load a CA certificate.
- *
- * This method does not add the loaded CA certificate to the internal
- * credentail set, but returns it only.
- *
- * @param filename file to load CA cert from
- * @return loaded certificate, or NULL
- */
- certificate_t* (*load_ca)(stroke_cred_t *this, char *filename);
-
- /**
* Load a peer certificate and serve it through the credential_set.
*
* @param filename file to load peer cert from
@@ -103,6 +94,6 @@ struct stroke_cred_t {
/**
* Create a stroke_cred instance.
*/
-stroke_cred_t *stroke_cred_create();
+stroke_cred_t *stroke_cred_create(stroke_ca_t *ca);
#endif /** STROKE_CRED_H_ @}*/
diff --git a/src/libcharon/plugins/stroke/stroke_list.c b/src/libcharon/plugins/stroke/stroke_list.c
index 68b8232bc..c7e4c9c65 100644
--- a/src/libcharon/plugins/stroke/stroke_list.c
+++ b/src/libcharon/plugins/stroke/stroke_list.c
@@ -647,7 +647,7 @@ METHOD(stroke_list_t, status, void,
enumerator->destroy(enumerator);
half_open = charon->ike_sa_manager->get_half_open_count(
- charon->ike_sa_manager, NULL);
+ charon->ike_sa_manager, NULL, FALSE);
fprintf(out, "Security Associations (%u up, %u connecting):\n",
charon->ike_sa_manager->get_count(charon->ike_sa_manager) - half_open,
half_open);
diff --git a/src/libcharon/plugins/stroke/stroke_socket.c b/src/libcharon/plugins/stroke/stroke_socket.c
index db7e66f14..29563e32f 100644
--- a/src/libcharon/plugins/stroke/stroke_socket.c
+++ b/src/libcharon/plugins/stroke/stroke_socket.c
@@ -779,10 +779,10 @@ stroke_socket_t *stroke_socket_create()
"%s.plugins.stroke.prevent_loglevel_changes", FALSE, lib->ns),
);
- this->cred = stroke_cred_create();
+ this->ca = stroke_ca_create();
+ this->cred = stroke_cred_create(this->ca);
this->attribute = stroke_attribute_create();
this->handler = stroke_handler_create();
- this->ca = stroke_ca_create(this->cred);
this->config = stroke_config_create(this->ca, this->cred, this->attribute);
this->control = stroke_control_create();
this->list = stroke_list_create(this->attribute);
diff --git a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_renew_session_job.h b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_renew_session_job.h
index 91e8fe404..f1587a1f6 100644
--- a/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_renew_session_job.h
+++ b/src/libcharon/plugins/tnc_ifmap/tnc_ifmap_renew_session_job.h
@@ -15,7 +15,7 @@
/**
* @defgroup tnc_ifmap_renew_session_job tnc_ifmap_renew_session_job
- * @{ @ingroup cjobs
+ * @{ @ingroup tnc_ifmap
*/
#ifndef TNC_IFMAP_RENEW_SESSION_JOB_H_
diff --git a/src/libcharon/plugins/uci/uci_control.c b/src/libcharon/plugins/uci/uci_control.c
index cebc389e7..a7d26e67d 100644
--- a/src/libcharon/plugins/uci/uci_control.c
+++ b/src/libcharon/plugins/uci/uci_control.c
@@ -147,7 +147,7 @@ static void initiate(private_uci_control_t *this, char *name)
if (enumerator->enumerate(enumerator, &child_cfg) &&
charon->controller->initiate(charon->controller, peer_cfg,
child_cfg->get_ref(child_cfg),
- controller_cb_empty, NULL, 0) == SUCCESS)
+ controller_cb_empty, NULL, 0, FALSE) == SUCCESS)
{
write_fifo(this, "connection '%s' established\n", name);
}
diff --git a/src/libcharon/plugins/updown/updown_listener.c b/src/libcharon/plugins/updown/updown_listener.c
index be65d599f..96282bee0 100644
--- a/src/libcharon/plugins/updown/updown_listener.c
+++ b/src/libcharon/plugins/updown/updown_listener.c
@@ -169,31 +169,34 @@ static void push_dns_env(private_updown_listener_t *this, ike_sa_t *ike_sa,
}
/**
- * Push variables for local virtual IPs
+ * Push variables for local/remote virtual IPs
*/
static void push_vip_env(private_updown_listener_t *this, ike_sa_t *ike_sa,
- char *envp[], u_int count)
+ char *envp[], u_int count, bool local)
{
enumerator_t *enumerator;
host_t *host;
int v4 = 0, v6 = 0;
bool first = TRUE;
- enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
+ enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, local);
while (enumerator->enumerate(enumerator, &host))
{
if (first)
{ /* legacy variable for first VIP */
first = FALSE;
- push_env(envp, count, "PLUTO_MY_SOURCEIP=%H", host);
+ push_env(envp, count, "PLUTO_%s_SOURCEIP=%H",
+ local ? "MY" : "PEER", host);
}
switch (host->get_family(host))
{
case AF_INET:
- push_env(envp, count, "PLUTO_MY_SOURCEIP4_%d=%H", ++v4, host);
+ push_env(envp, count, "PLUTO_%s_SOURCEIP4_%d=%H",
+ local ? "MY" : "PEER", ++v4, host);
break;
case AF_INET6:
- push_env(envp, count, "PLUTO_MY_SOURCEIP6_%d=%H", ++v6, host);
+ push_env(envp, count, "PLUTO_%s_SOURCEIP6_%d=%H",
+ local ? "MY" : "PEER", ++v6, host);
break;
default:
continue;
@@ -313,7 +316,8 @@ static void invoke_once(private_updown_listener_t *this, ike_sa_t *ike_sa,
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));
+ push_vip_env(this, ike_sa, envp, countof(envp), TRUE);
+ push_vip_env(this, ike_sa, envp, countof(envp), FALSE);
mark = config->get_mark(config, TRUE);
if (mark.value)
{
diff --git a/src/libcharon/plugins/vici/Makefile.am b/src/libcharon/plugins/vici/Makefile.am
index b25396085..c99d23e4e 100644
--- a/src/libcharon/plugins/vici/Makefile.am
+++ b/src/libcharon/plugins/vici/Makefile.am
@@ -23,6 +23,7 @@ libstrongswan_vici_la_SOURCES = \
vici_config.h vici_config.c \
vici_cred.h vici_cred.c \
vici_attribute.h vici_attribute.c \
+ vici_authority.h vici_authority.c \
vici_logger.h vici_logger.c \
vici_plugin.h vici_plugin.c
diff --git a/src/libcharon/plugins/vici/Makefile.in b/src/libcharon/plugins/vici/Makefile.in
index b63226daa..1a7870ae9 100644
--- a/src/libcharon/plugins/vici/Makefile.in
+++ b/src/libcharon/plugins/vici/Makefile.in
@@ -136,7 +136,7 @@ libstrongswan_vici_la_LIBADD =
am_libstrongswan_vici_la_OBJECTS = vici_socket.lo vici_message.lo \
vici_builder.lo vici_dispatcher.lo vici_query.lo \
vici_control.lo vici_config.lo vici_cred.lo vici_attribute.lo \
- vici_logger.lo vici_plugin.lo
+ vici_authority.lo vici_logger.lo vici_plugin.lo
libstrongswan_vici_la_OBJECTS = $(am_libstrongswan_vici_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
@@ -543,6 +543,7 @@ libstrongswan_vici_la_SOURCES = \
vici_config.h vici_config.c \
vici_cred.h vici_cred.c \
vici_attribute.h vici_attribute.c \
+ vici_authority.h vici_authority.c \
vici_logger.h vici_logger.c \
vici_plugin.h vici_plugin.c
@@ -736,6 +737,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libvici.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_attribute.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_authority.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_builder.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_config.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/vici_control.Plo@am__quote@
diff --git a/src/libcharon/plugins/vici/README.md b/src/libcharon/plugins/vici/README.md
index 0ce4271b0..e20e8ab26 100644
--- a/src/libcharon/plugins/vici/README.md
+++ b/src/libcharon/plugins/vici/README.md
@@ -259,6 +259,7 @@ Initiates an SA while streaming _control-log_ events.
{
child = <CHILD_SA configuration name to initiate>
timeout = <timeout in seconds before returning>
+ init-limits = <whether limits may prevent initiating the CHILD_SA>
loglevel = <loglevel to issue "control-log" events for>
} => {
success = <yes or no>
@@ -366,6 +367,27 @@ over vici.
# completes after streaming list-cert events
}
+### list-authorities() ###
+
+List currently loaded certification authority information by streaming
+_list-authority_ events.
+
+ {
+ name = <list certification authority of a given name>
+ } => {
+ # completes after streaming list-authority events
+ }
+
+### get-authorities() ###
+
+Return a list of currently loaded certification authority names.
+
+ {} => {
+ authorities = [
+ <list of certification authority names>
+ ]
+ }
+
### load-conn() ###
Load a single connection definition into the daemon. An existing connection
@@ -442,6 +464,32 @@ credential cache.
errmsg = <error string on failure>
}
+### load-authority() ###
+
+Load a single certification authority definition into the daemon. An existing
+authority with the same name gets replaced.
+
+ {
+ <certification authority name> = {
+ # certification authority parameters
+ # refer to swanctl.conf(5) for details.
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+ }
+
+### unload-authority() ###
+
+Unload a previously loaded certification authority definition by name.
+
+ {
+ name = <certification authority name>
+ } => {
+ success = <yes or no>
+ errmsg = <error string on failure>
+ }
+
### load-pool() ###
Load an in-memory virtual IP and configuration attribute pool. Existing
@@ -673,6 +721,82 @@ _list-certs_ command.
data = <ASN1 encoded certificate data>
}
+### list-authority ###
+
+The _list-authority_ event is issued to stream loaded certification authority
+information during an active_list-authorities_ command.
+
+ {
+ <certification authority name> = {
+ cacert = <subject distinguished name of CA certificate>
+ crl_uris = [
+ <CRL URI (http, ldap or file)>
+ ]
+ ocsp_uris = [
+ <OCSP URI (http)>
+ ]
+ cert_uri_base = <base URI for download of hash-and-URL certificates>
+ }
+ }
+
+### ike-updown ###
+
+The _ike-updown_ event is issued when an IKE_SA is established or terminated.
+
+ {
+ up = <yes or no>
+ <IKE_SA config name> = {
+ <same data as in the list-sas event, but without child-sas section>
+ }
+ }
+
+### ike-rekey ###
+
+The _ike-rekey_ event is issued when an IKE_SA is rekeyed.
+
+ {
+ <IKE_SA config name> = {
+ old = {
+ <same data as in the list-sas event, but without child-sas section>
+ }
+ new = {
+ <same data as in the list-sas event, but without child-sas section>
+ }
+ }
+ }
+
+### child-updown ###
+
+The _child-updown_ event is issued when a CHILD_SA is established or terminated.
+
+ {
+ up = <yes or no>
+ <IKE_SA config name> = {
+ <same data as in the list-sas event, but with only the affected
+ CHILD_SA in the child-sas section>
+ }
+ }
+
+### child-rekey ###
+
+The _child-rekey_ event is issued when a CHILD_SA is rekeyed.
+
+ {
+ <IKE_SA config name> = {
+ <same data as in the list-sas event, but with the child-sas section
+ as follows>
+ child-sas = {
+ <child-sa-name> = {
+ old = {
+ <same data as in the list-sas event>
+ }
+ new = {
+ <same data as in the list-sas event>
+ }
+ }
+ }
+ }
+ }
# libvici C client library #
diff --git a/src/libcharon/plugins/vici/python/LICENSE b/src/libcharon/plugins/vici/python/LICENSE
index 111523ca8..54f2158dc 100644
--- a/src/libcharon/plugins/vici/python/LICENSE
+++ b/src/libcharon/plugins/vici/python/LICENSE
@@ -1,4 +1,6 @@
Copyright (c) 2015 Björn Schuberg
+Copyright (c) 2015 Martin Willi
+Copyright (c) 2015 Tobias Brunner
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/src/libcharon/plugins/vici/python/vici/exception.py b/src/libcharon/plugins/vici/python/vici/exception.py
index 36384e556..757ac51a9 100644
--- a/src/libcharon/plugins/vici/python/vici/exception.py
+++ b/src/libcharon/plugins/vici/python/vici/exception.py
@@ -8,3 +8,6 @@ class SessionException(Exception):
class CommandException(Exception):
"""Command result exception."""
+
+class EventUnknownException(Exception):
+ """Event unknown exception."""
diff --git a/src/libcharon/plugins/vici/python/vici/session.py b/src/libcharon/plugins/vici/python/vici/session.py
index dee58699d..283e3d13d 100644
--- a/src/libcharon/plugins/vici/python/vici/session.py
+++ b/src/libcharon/plugins/vici/python/vici/session.py
@@ -1,7 +1,7 @@
import collections
import socket
-from .exception import SessionException, CommandException
+from .exception import SessionException, CommandException, EventUnknownException
from .protocol import Transport, Packet, Message
@@ -197,6 +197,16 @@ class Session(object):
"""
return self.handler.request("get-pools")
+ def listen(self, event_types):
+ """Register and listen for the given events.
+
+ :param event_types: event types to register
+ :type event_types: list
+ :return: generator for streamed event responses as (event_type, dict)
+ :rtype: generator
+ """
+ return self.handler.listen(event_types)
+
class SessionHandler(object):
"""Handles client command execution requests over vici."""
@@ -215,6 +225,32 @@ class SessionHandler(object):
self.transport.send(packet)
return Packet.parse(self.transport.receive())
+ def _register_unregister(self, event_type, register):
+ """Register or unregister for the given event.
+
+ :param event_type: event to register
+ :type event_type: str
+ :param register: whether to register or unregister
+ :type register: bool
+ """
+ if register:
+ packet = Packet.register_event(event_type)
+ else:
+ packet = Packet.unregister_event(event_type)
+ response = self._communicate(packet)
+ if response.response_type == Packet.EVENT_UNKNOWN:
+ raise EventUnknownException(
+ "Unknown event type '{event}'".format(event=event_type)
+ )
+ elif response.response_type != Packet.EVENT_CONFIRM:
+ raise SessionException(
+ "Unexpected response type {type}, "
+ "expected '{confirm}' (EVENT_CONFIRM)".format(
+ type=response.response_type,
+ confirm=Packet.EVENT_CONFIRM,
+ )
+ )
+
def request(self, command, message=None):
"""Send request with an optional message.
@@ -265,57 +301,37 @@ class SessionHandler(object):
if message is not None:
message = Message.serialize(message)
- # subscribe to event stream
- packet = Packet.register_event(event_stream_type)
- response = self._communicate(packet)
-
- if response.response_type != Packet.EVENT_CONFIRM:
- raise SessionException(
- "Unexpected response type {type}, "
- "expected '{confirm}' (EVENT_CONFIRM)".format(
- type=response.response_type,
- confirm=Packet.EVENT_CONFIRM,
- )
- )
-
- # issue command, and read any event messages
- packet = Packet.request(command, message)
- self.transport.send(packet)
- exited = False
- while True:
- response = Packet.parse(self.transport.receive())
- if response.response_type == Packet.EVENT:
- if not exited:
- try:
- yield Message.deserialize(response.payload)
- except GeneratorExit:
- exited = True
- pass
+ self._register_unregister(event_stream_type, True);
+
+ try:
+ packet = Packet.request(command, message)
+ self.transport.send(packet)
+ exited = False
+ while True:
+ response = Packet.parse(self.transport.receive())
+ if response.response_type == Packet.EVENT:
+ if not exited:
+ try:
+ yield Message.deserialize(response.payload)
+ except GeneratorExit:
+ exited = True
+ pass
+ else:
+ break
+
+ if response.response_type == Packet.CMD_RESPONSE:
+ command_response = Message.deserialize(response.payload)
else:
- break
-
- if response.response_type == Packet.CMD_RESPONSE:
- command_response = Message.deserialize(response.payload)
- else:
- raise SessionException(
- "Unexpected response type {type}, "
- "expected '{response}' (CMD_RESPONSE)".format(
- type=response.response_type,
- response=Packet.CMD_RESPONSE
+ raise SessionException(
+ "Unexpected response type {type}, "
+ "expected '{response}' (CMD_RESPONSE)".format(
+ type=response.response_type,
+ response=Packet.CMD_RESPONSE
+ )
)
- )
- # unsubscribe from event stream
- packet = Packet.unregister_event(event_stream_type)
- response = self._communicate(packet)
- if response.response_type != Packet.EVENT_CONFIRM:
- raise SessionException(
- "Unexpected response type {type}, "
- "expected '{confirm}' (EVENT_CONFIRM)".format(
- type=response.response_type,
- confirm=Packet.EVENT_CONFIRM,
- )
- )
+ finally:
+ self._register_unregister(event_stream_type, False);
# evaluate command result, if any
if "success" in command_response:
@@ -325,3 +341,27 @@ class SessionHandler(object):
errmsg=command_response["errmsg"]
)
)
+
+ def listen(self, event_types):
+ """Register and listen for the given events.
+
+ :param event_types: event types to register
+ :type event_types: list
+ :return: generator for streamed event responses as (event_type, dict)
+ :rtype: generator
+ """
+ for event_type in event_types:
+ self._register_unregister(event_type, True)
+
+ try:
+ while True:
+ response = Packet.parse(self.transport.receive())
+ if response.response_type == Packet.EVENT:
+ try:
+ yield response.event_type, Message.deserialize(response.payload)
+ except GeneratorExit:
+ break
+
+ finally:
+ for event_type in event_types:
+ self._register_unregister(event_type, False)
diff --git a/src/libcharon/plugins/vici/ruby/lib/vici.rb b/src/libcharon/plugins/vici/ruby/lib/vici.rb
index f87e46e69..f8169add0 100644
--- a/src/libcharon/plugins/vici/ruby/lib/vici.rb
+++ b/src/libcharon/plugins/vici/ruby/lib/vici.rb
@@ -247,7 +247,11 @@ module Vici
def recv_all(len)
encoding = ""
while encoding.length < len do
- encoding << @socket.recv(len - encoding.length)
+ data = @socket.recv(len - encoding.length)
+ if data.empty?
+ raise TransportError, "connection closed"
+ end
+ encoding << data
end
encoding
end
diff --git a/src/libcharon/plugins/vici/suites/test_message.c b/src/libcharon/plugins/vici/suites/test_message.c
index e76d27332..045e34fff 100644
--- a/src/libcharon/plugins/vici/suites/test_message.c
+++ b/src/libcharon/plugins/vici/suites/test_message.c
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
@@ -355,6 +358,33 @@ START_TEST(test_get_int)
}
END_TEST
+START_TEST(test_get_bool)
+{
+ vici_message_t *m;
+
+ m = build_getter_msg();
+
+ ck_assert(m->get_bool(m, TRUE, "key1"));
+ ck_assert(m->get_bool(m, FALSE, "key1"));
+
+ ck_assert(m->get_bool(m, TRUE, "section1.key2"));
+ ck_assert(m->get_bool(m, TRUE, "section1.section2.key3"));
+ ck_assert(m->get_bool(m, TRUE, "section1.key4"));
+ ck_assert(m->get_bool(m, TRUE, "key5"));
+ ck_assert(m->get_bool(m, TRUE, "nonexistent"));
+ ck_assert(m->get_bool(m, TRUE, "n.o.n.e.x.i.s.t.e.n.t"));
+
+ ck_assert(!m->get_bool(m, FALSE, "section1.key2"));
+ ck_assert(!m->get_bool(m, FALSE, "section1.section2.key3"));
+ ck_assert(!m->get_bool(m, FALSE, "section1.key4"));
+ ck_assert(!m->get_bool(m, FALSE, "key5"));
+ ck_assert(!m->get_bool(m, FALSE, "nonexistent"));
+ ck_assert(!m->get_bool(m, FALSE, "n.o.n.e.x.i.s.t.e.n.t"));
+
+ m->destroy(m);
+}
+END_TEST
+
START_TEST(test_get_value)
{
vici_message_t *m;
@@ -400,6 +430,7 @@ Suite *message_suite_create()
tc = tcase_create("convenience getters");
tcase_add_test(tc, test_get_str);
tcase_add_test(tc, test_get_int);
+ tcase_add_test(tc, test_get_bool);
tcase_add_test(tc, test_get_value);
suite_add_tcase(s, tc);
diff --git a/src/libcharon/plugins/vici/vici_authority.c b/src/libcharon/plugins/vici/vici_authority.c
new file mode 100644
index 000000000..94a7f68f6
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_authority.c
@@ -0,0 +1,750 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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.
+ */
+
+#define _GNU_SOURCE
+
+#include "vici_authority.h"
+#include "vici_builder.h"
+
+#include <threading/rwlock.h>
+#include <collections/linked_list.h>
+#include <credentials/certificates/x509.h>
+#include <utils/debug.h>
+
+#include <stdio.h>
+
+typedef struct private_vici_authority_t private_vici_authority_t;
+
+/**
+ * Private data of an vici_authority_t object.
+ */
+struct private_vici_authority_t {
+
+ /**
+ * Public vici_authority_t interface.
+ */
+ vici_authority_t public;
+
+ /**
+ * Dispatcher
+ */
+ vici_dispatcher_t *dispatcher;
+
+ /**
+ * credential backend managed by VICI used for our ca certificates
+ */
+ vici_cred_t *cred;
+
+ /**
+ * List of certification authorities
+ */
+ linked_list_t *authorities;
+
+ /**
+ * rwlock to lock access to certification authorities
+ */
+ rwlock_t *lock;
+
+};
+
+typedef struct authority_t authority_t;
+
+/**
+ * loaded certification authorities
+ */
+struct authority_t {
+
+ /**
+ * Name of the certification authoritiy
+ */
+ char *name;
+
+ /**
+ * Reference to CA certificate
+ */
+ certificate_t *cert;
+
+ /**
+ * CRL URIs
+ */
+ linked_list_t *crl_uris;
+
+ /**
+ * OCSP URIs
+ */
+ linked_list_t *ocsp_uris;
+
+ /**
+ * Hashes of certificates issued by this CA
+ */
+ linked_list_t *hashes;
+
+ /**
+ * Base URI used for certificates from this CA
+ */
+ char *cert_uri_base;
+};
+
+/**
+ * create a new certification authority
+ */
+static authority_t *authority_create(char *name)
+{
+ authority_t *authority;
+
+ INIT(authority,
+ .name = strdup(name),
+ .crl_uris = linked_list_create(),
+ .ocsp_uris = linked_list_create(),
+ .hashes = linked_list_create(),
+ );
+
+ return authority;
+}
+
+/**
+ * destroy a certification authority
+ */
+static void authority_destroy(authority_t *this)
+{
+ this->crl_uris->destroy_function(this->crl_uris, free);
+ this->ocsp_uris->destroy_function(this->ocsp_uris, free);
+ this->hashes->destroy_offset(this->hashes, offsetof(identification_t, destroy));
+ DESTROY_IF(this->cert);
+ free(this->cert_uri_base);
+ free(this->name);
+ free(this);
+}
+
+
+/**
+ * Create a (error) reply message
+ */
+static vici_message_t* create_reply(char *fmt, ...)
+{
+ vici_builder_t *builder;
+ va_list args;
+
+ builder = vici_builder_create();
+ builder->add_kv(builder, "success", fmt ? "no" : "yes");
+ if (fmt)
+ {
+ va_start(args, fmt);
+ builder->vadd_kv(builder, "errmsg", fmt, args);
+ va_end(args);
+ }
+ return builder->finalize(builder);
+}
+
+/**
+ * A rule to parse a key/value or list item
+ */
+typedef struct {
+ /** name of the key/value or list */
+ char *name;
+ /** function to parse value */
+ bool (*parse)(void *out, chunk_t value);
+ /** result, passed to parse() */
+ void *out;
+} parse_rule_t;
+
+/**
+ * Parse key/values using a rule-set
+ */
+static bool parse_rules(parse_rule_t *rules, int count, char *name,
+ chunk_t value, vici_message_t **reply)
+{
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ if (streq(name, rules[i].name))
+ {
+ if (rules[i].parse(rules[i].out, value))
+ {
+ return TRUE;
+ }
+ *reply = create_reply("invalid value for: %s, authority discarded",
+ name);
+ return FALSE;
+ }
+ }
+ *reply = create_reply("unknown option: %s, authority discarded", name);
+ return FALSE;
+}
+
+/**
+ * Parse callback data, passed to each callback
+ */
+typedef struct {
+ private_vici_authority_t *this;
+ vici_message_t *reply;
+} request_data_t;
+
+/**
+ * Data associated with an authority load
+ */
+typedef struct {
+ request_data_t *request;
+ authority_t *authority;
+} load_data_t;
+
+/**
+ * Parse a string
+ */
+CALLBACK(parse_string, bool,
+ char **str, chunk_t v)
+{
+ if (!chunk_printable(v, NULL, ' '))
+ {
+ return FALSE;
+ }
+ *str = strndup(v.ptr, v.len);
+
+ return TRUE;
+}
+
+/**
+ * Parse list of URIs
+ */
+CALLBACK(parse_uris, bool,
+ linked_list_t *out, chunk_t v)
+{
+ char *uri;
+
+ if (!chunk_printable(v, NULL, ' '))
+ {
+ return FALSE;
+ }
+ uri = strndup(v.ptr, v.len);
+ out->insert_last(out, uri);
+
+ return TRUE;
+}
+
+/**
+ * Parse a CA certificate
+ */
+CALLBACK(parse_cacert, bool,
+ certificate_t **cacert, chunk_t v)
+{
+ certificate_t *cert;
+ x509_t *x509;
+
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_PEM, v, BUILD_END);
+ if (!cert)
+ {
+ return create_reply("parsing %N certificate failed",
+ certificate_type_names, CERT_X509);
+ }
+ x509 = (x509_t*)cert;
+
+ if ((x509->get_flags(x509) & X509_CA) != X509_CA)
+ {
+ cert->destroy(cert);
+ return create_reply("certificate without CA flag, rejected");
+ }
+ *cacert = cert;
+
+ return TRUE;
+}
+
+CALLBACK(authority_kv, bool,
+ load_data_t *data, vici_message_t *message, char *name, chunk_t value)
+{
+ parse_rule_t rules[] = {
+ { "cacert", parse_cacert, &data->authority->cert },
+ { "cert_uri_base", parse_string, &data->authority->cert_uri_base },
+ };
+
+ return parse_rules(rules, countof(rules), name, value,
+ &data->request->reply);
+}
+
+CALLBACK(authority_li, bool,
+ load_data_t *data, vici_message_t *message, char *name, chunk_t value)
+{
+ parse_rule_t rules[] = {
+ { "crl_uris", parse_uris, data->authority->crl_uris },
+ { "ocsp_uris", parse_uris, data->authority->ocsp_uris },
+ };
+
+ return parse_rules(rules, countof(rules), name, value,
+ &data->request->reply);
+}
+
+static void log_authority_data(authority_t *authority)
+{
+ enumerator_t *enumerator;
+ identification_t *subject;
+ bool first = TRUE;
+ char *uri;
+
+ subject = authority->cert->get_subject(authority->cert);
+ DBG2(DBG_CFG, " cacert = %Y", subject);
+
+ enumerator = authority->crl_uris->create_enumerator(authority->crl_uris);
+ while (enumerator->enumerate(enumerator, &uri))
+ {
+ if (first)
+ {
+ DBG2(DBG_CFG, " crl_uris = %s", uri);
+ first = FALSE;
+ }
+ else
+ {
+ DBG2(DBG_CFG, " %s", uri);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ first = TRUE;
+ enumerator = authority->ocsp_uris->create_enumerator(authority->ocsp_uris);
+ while (enumerator->enumerate(enumerator, &uri))
+ {
+ if (first)
+ {
+ DBG2(DBG_CFG, " ocsp_uris = %s", uri);
+ first = FALSE;
+ }
+ else
+ {
+ DBG2(DBG_CFG, " %s", uri);
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (authority->cert_uri_base)
+ {
+ DBG2(DBG_CFG, " cert_uri_base = %s", authority->cert_uri_base);
+ }
+}
+
+CALLBACK(authority_sn, bool,
+ request_data_t *request, vici_message_t *message,
+ vici_parse_context_t *ctx, char *name)
+{
+ enumerator_t *enumerator;
+ linked_list_t *authorities;
+ authority_t *authority;
+ vici_cred_t *cred;
+
+ load_data_t data = {
+ .request = request,
+ .authority = authority_create(name),
+ };
+
+ DBG2(DBG_CFG, " authority %s:", name);
+
+ if (!message->parse(message, ctx, NULL, authority_kv, authority_li, &data) ||
+ !data.authority->cert)
+ {
+ authority_destroy(data.authority);
+ return FALSE;
+ }
+ log_authority_data(data.authority);
+
+ request->this->lock->write_lock(request->this->lock);
+
+ authorities = request->this->authorities;
+ enumerator = authorities->create_enumerator(authorities);
+ while (enumerator->enumerate(enumerator, &authority))
+ {
+ if (streq(authority->name, name))
+ {
+ /* remove the old authority definition */
+ authorities->remove_at(authorities, enumerator);
+ authority_destroy(authority);
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ authorities->insert_last(authorities, data.authority);
+
+ cred = request->this->cred;
+ data.authority->cert = cred->add_cert(cred, data.authority->cert);
+
+ request->this->lock->unlock(request->this->lock);
+
+ return TRUE;
+}
+
+CALLBACK(load_authority, vici_message_t*,
+ private_vici_authority_t *this, char *name, u_int id, vici_message_t *message)
+{
+ request_data_t request = {
+ .this = this,
+ };
+
+ if (!message->parse(message, NULL, authority_sn, NULL, NULL, &request))
+ {
+ if (request.reply)
+ {
+ return request.reply;
+ }
+ return create_reply("parsing request failed");
+ }
+ return create_reply(NULL);
+}
+
+CALLBACK(unload_authority, vici_message_t*,
+ private_vici_authority_t *this, char *name, u_int id, vici_message_t *message)
+{
+ enumerator_t *enumerator;
+ authority_t *authority;
+ char *authority_name;
+ bool found = FALSE;
+
+ authority_name = message->get_str(message, NULL, "name");
+ if (!authority_name)
+ {
+ return create_reply("unload: missing authority name");
+ }
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->authorities->create_enumerator(this->authorities);
+ while (enumerator->enumerate(enumerator, &authority))
+ {
+ if (streq(authority->name, authority_name))
+ {
+ this->authorities->remove_at(this->authorities, enumerator);
+ authority_destroy(authority);
+ found = TRUE;
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ if (!found)
+ {
+ return create_reply("unload: authority '%s' not found", authority_name);
+ }
+ return create_reply(NULL);
+}
+
+CALLBACK(get_authorities, vici_message_t*,
+ private_vici_authority_t *this, char *name, u_int id,
+ vici_message_t *message)
+{
+ vici_builder_t *builder;
+ enumerator_t *enumerator;
+ authority_t *authority;
+
+ builder = vici_builder_create();
+ builder->begin_list(builder, "authorities");
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->authorities->create_enumerator(this->authorities);
+ while (enumerator->enumerate(enumerator, &authority))
+ {
+ builder->add_li(builder, "%s", authority->name);
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ builder->end_list(builder);
+
+ return builder->finalize(builder);
+}
+
+CALLBACK(list_authorities, vici_message_t*,
+ private_vici_authority_t *this, char *name, u_int id, vici_message_t *request)
+{
+ enumerator_t *enumerator, *e;
+ authority_t *authority;
+ vici_builder_t *b;
+ char *str, *uri;
+
+ str = request->get_str(request, NULL, "name");
+
+ this->lock->read_lock(this->lock);
+ enumerator = this->authorities->create_enumerator(this->authorities);
+ while (enumerator->enumerate(enumerator, &authority))
+ {
+ if (str && !streq(str, authority->name))
+ {
+ continue;
+ }
+ b = vici_builder_create();
+
+ /* open authority section */
+ b->begin_section(b, authority->name);
+
+ /* subject DN of cacert */
+ b->add_kv(b, "cacert", "%Y",
+ authority->cert->get_subject(authority->cert));
+
+ /* list of crl_uris */
+ b->begin_list(b, "crl_uris");
+ e = authority->crl_uris->create_enumerator(authority->crl_uris);
+ while (e->enumerate(e, &uri))
+ {
+ b->add_li(b, "%s", uri);
+ }
+ e->destroy(e);
+ b->end_list(b);
+
+ /* list of ocsp_uris */
+ b->begin_list(b, "ocsp_uris");
+ e = authority->ocsp_uris->create_enumerator(authority->ocsp_uris);
+ while (e->enumerate(e, &uri))
+ {
+ b->add_li(b, "%s", uri);
+ }
+ e->destroy(e);
+ b->end_list(b);
+
+ /* cert_uri_base */
+ if (authority->cert_uri_base)
+ {
+ b->add_kv(b, "cert_uri_base", "%s", authority->cert_uri_base);
+ }
+
+ /* close authority and raise event */
+ b->end_section(b);
+ this->dispatcher->raise_event(this->dispatcher, "list-authority", id,
+ b->finalize(b));
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ b = vici_builder_create();
+ return b->finalize(b);
+}
+
+static void manage_command(private_vici_authority_t *this,
+ char *name, vici_command_cb_t cb, bool reg)
+{
+ this->dispatcher->manage_command(this->dispatcher, name,
+ reg ? cb : NULL, this);
+}
+
+/**
+ * (Un-)register dispatcher functions
+ */
+static void manage_commands(private_vici_authority_t *this, bool reg)
+{
+ this->dispatcher->manage_event(this->dispatcher, "list-authority", reg);
+
+ manage_command(this, "load-authority", load_authority, reg);
+ manage_command(this, "unload-authority", unload_authority, reg);
+ manage_command(this, "get-authorities", get_authorities, reg);
+ manage_command(this, "list-authorities", list_authorities, reg);
+}
+
+/**
+ * data to pass to create_inner_cdp
+ */
+typedef struct {
+ private_vici_authority_t *this;
+ certificate_type_t type;
+ identification_t *id;
+} cdp_data_t;
+
+/**
+ * destroy cdp enumerator data and unlock list
+ */
+static void cdp_data_destroy(cdp_data_t *data)
+{
+ data->this->lock->unlock(data->this->lock);
+ free(data);
+}
+
+/**
+ * inner enumerator constructor for CDP URIs
+ */
+static enumerator_t *create_inner_cdp(authority_t *authority, cdp_data_t *data)
+{
+ public_key_t *public;
+ enumerator_t *enumerator = NULL;
+ linked_list_t *list;
+
+ if (data->type == CERT_X509_OCSP_RESPONSE)
+ {
+ list = authority->ocsp_uris;
+ }
+ else
+ {
+ list = authority->crl_uris;
+ }
+
+ public = authority->cert->get_public_key(authority->cert);
+ if (public)
+ {
+ if (!data->id)
+ {
+ enumerator = list->create_enumerator(list);
+ }
+ else
+ {
+ if (public->has_fingerprint(public, data->id->get_encoding(data->id)))
+ {
+ enumerator = list->create_enumerator(list);
+ }
+ }
+ public->destroy(public);
+ }
+ return enumerator;
+}
+
+/**
+ * inner enumerator constructor for "Hash and URL"
+ */
+static enumerator_t *create_inner_cdp_hashandurl(authority_t *authority,
+ cdp_data_t *data)
+{
+ enumerator_t *enumerator = NULL, *hash_enum;
+ identification_t *current;
+
+ if (!data->id || !authority->cert_uri_base)
+ {
+ return NULL;
+ }
+
+ hash_enum = authority->hashes->create_enumerator(authority->hashes);
+ while (hash_enum->enumerate(hash_enum, &current))
+ {
+ if (current->matches(current, data->id))
+ {
+ char *url, *hash;
+
+ url = malloc(strlen(authority->cert_uri_base) + 40 + 1);
+ strcpy(url, authority->cert_uri_base);
+ hash = chunk_to_hex(current->get_encoding(current), NULL, FALSE).ptr;
+ strncat(url, hash, 40);
+ free(hash);
+
+ enumerator = enumerator_create_single(url, free);
+ break;
+ }
+ }
+ hash_enum->destroy(hash_enum);
+ return enumerator;
+}
+
+METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*,
+ private_vici_authority_t *this, certificate_type_t type,
+ identification_t *id)
+{
+ cdp_data_t *data;
+
+ switch (type)
+ { /* we serve CRLs, OCSP responders and URLs for "Hash and URL" */
+ case CERT_X509:
+ case CERT_X509_CRL:
+ case CERT_X509_OCSP_RESPONSE:
+ case CERT_ANY:
+ break;
+ default:
+ return NULL;
+ }
+ data = malloc_thing(cdp_data_t);
+ data->this = this;
+ data->type = type;
+ data->id = id;
+
+ this->lock->read_lock(this->lock);
+
+ return enumerator_create_nested(
+ this->authorities->create_enumerator(this->authorities),
+ (type == CERT_X509) ? (void*)create_inner_cdp_hashandurl :
+ (void*)create_inner_cdp, data, (void*)cdp_data_destroy);
+}
+
+METHOD(vici_authority_t, check_for_hash_and_url, void,
+ private_vici_authority_t *this, certificate_t* cert)
+{
+ authority_t *authority;
+ enumerator_t *enumerator;
+ hasher_t *hasher;
+
+ hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+ if (hasher == NULL)
+ {
+ DBG1(DBG_CFG, "unable to use hash-and-url: sha1 not supported");
+ return;
+ }
+
+ this->lock->write_lock(this->lock);
+ enumerator = this->authorities->create_enumerator(this->authorities);
+ while (enumerator->enumerate(enumerator, &authority))
+ {
+ if (authority->cert_uri_base &&
+ cert->issued_by(cert, authority->cert, NULL))
+ {
+ chunk_t hash, encoded;
+
+ if (cert->get_encoding(cert, CERT_ASN1_DER, &encoded))
+ {
+ if (hasher->allocate_hash(hasher, encoded, &hash))
+ {
+ authority->hashes->insert_last(authority->hashes,
+ identification_create_from_encoding(ID_KEY_ID, hash));
+ chunk_free(&hash);
+ }
+ chunk_free(&encoded);
+ }
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
+
+ hasher->destroy(hasher);
+}
+
+METHOD(vici_authority_t, destroy, void,
+ private_vici_authority_t *this)
+{
+ manage_commands(this, FALSE);
+
+ this->authorities->destroy_function(this->authorities,
+ (void*)authority_destroy);
+ this->lock->destroy(this->lock);
+ free(this);
+}
+
+/**
+ * See header
+ */
+vici_authority_t *vici_authority_create(vici_dispatcher_t *dispatcher,
+ vici_cred_t *cred)
+{
+ private_vici_authority_t *this;
+
+ INIT(this,
+ .public = {
+ .set = {
+ .create_private_enumerator = (void*)return_null,
+ .create_cert_enumerator = (void*)return_null,
+ .create_shared_enumerator = (void*)return_null,
+ .create_cdp_enumerator = _create_cdp_enumerator,
+ .cache_cert = (void*)nop,
+ },
+ .check_for_hash_and_url = _check_for_hash_and_url,
+ .destroy = _destroy,
+ },
+ .dispatcher = dispatcher,
+ .cred = cred,
+ .authorities = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ );
+
+ manage_commands(this, TRUE);
+
+ return &this->public;
+}
diff --git a/src/libcharon/plugins/vici/vici_authority.h b/src/libcharon/plugins/vici/vici_authority.h
new file mode 100644
index 000000000..dbeabae62
--- /dev/null
+++ b/src/libcharon/plugins/vici/vici_authority.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 vici_authority vici_authority
+ * @{ @ingroup vici
+ */
+
+#ifndef VICI_AUTHORITY_H_
+#define VICI_AUTHORITY_H_
+
+#include "vici_dispatcher.h"
+#include "vici_cred.h"
+
+typedef struct vici_authority_t vici_authority_t;
+
+/**
+ * In-memory certification authority backend, managed by VICI.
+ */
+struct vici_authority_t {
+
+ /**
+ * Implements credential_set_t
+ */
+ credential_set_t set;
+
+ /**
+ * Check if a certificate can be made available through hash and URL.
+ *
+ * @param cert end entity certificate
+ */
+ void (*check_for_hash_and_url)(vici_authority_t *this, certificate_t* cert);
+
+ /**
+ * Destroy a vici_authority_t.
+ */
+ void (*destroy)(vici_authority_t *this);
+};
+
+/**
+ * Create a vici_authority instance.
+ *
+ * @param dispatcher dispatcher to receive requests from
+ * @param cred in-memory credential backend managed by VICI
+ * @return authority backend
+ */
+vici_authority_t *vici_authority_create(vici_dispatcher_t *dispatcher,
+ vici_cred_t *cred);
+
+#endif /** VICI_AUTHORITY_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_config.c b/src/libcharon/plugins/vici/vici_config.c
index d23259912..ea6d2958a 100644
--- a/src/libcharon/plugins/vici/vici_config.c
+++ b/src/libcharon/plugins/vici/vici_config.c
@@ -2,6 +2,9 @@
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
@@ -93,6 +96,12 @@ struct private_vici_config_t {
* Lock for conns list
*/
rwlock_t *lock;
+
+ /**
+ * Auxiliary certification authority information
+ */
+ vici_authority_t *authority;
+
};
METHOD(backend_t, create_peer_cfg_enumerator, enumerator_t*,
@@ -382,7 +391,7 @@ typedef struct {
char* updown;
bool hostaccess;
bool ipcomp;
- bool route;
+ bool policies;
ipsec_mode_t mode;
u_int32_t replay_window;
action_t dpd_action;
@@ -417,6 +426,7 @@ static void log_child_data(child_data_t *data, char *name)
DBG2(DBG_CFG, " hostaccess = %u", data->hostaccess);
DBG2(DBG_CFG, " ipcomp = %u", data->ipcomp);
DBG2(DBG_CFG, " mode = %N", ipsec_mode_names, data->mode);
+ DBG2(DBG_CFG, " policies = %u", data->policies);
if (data->replay_window != REPLAY_UNDEFINED)
{
DBG2(DBG_CFG, " replay_window = %u", data->replay_window);
@@ -1040,15 +1050,21 @@ CALLBACK(parse_group, bool,
/**
* Parse a certificate; add as auth rule to config
*/
-static bool parse_cert(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v)
+static bool parse_cert(auth_data_t *auth, auth_rule_t rule, chunk_t v)
{
+ vici_authority_t *authority;
certificate_t *cert;
cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_PEM, v, BUILD_END);
if (cert)
{
- cfg->add(cfg, rule, cert);
+ if (rule == AUTH_RULE_SUBJECT_CERT)
+ {
+ authority = auth->request->this->authority;
+ authority->check_for_hash_and_url(authority, cert);
+ }
+ auth->cfg->add(auth->cfg, rule, cert);
return TRUE;
}
return FALSE;
@@ -1058,18 +1074,18 @@ static bool parse_cert(auth_cfg_t *cfg, auth_rule_t rule, chunk_t v)
* Parse subject certificates
*/
CALLBACK(parse_certs, bool,
- auth_cfg_t *cfg, chunk_t v)
+ auth_data_t *auth, chunk_t v)
{
- return parse_cert(cfg, AUTH_RULE_SUBJECT_CERT, v);
+ return parse_cert(auth, AUTH_RULE_SUBJECT_CERT, v);
}
/**
* Parse CA certificates
*/
CALLBACK(parse_cacerts, bool,
- auth_cfg_t *cfg, chunk_t v)
+ auth_data_t *auth, chunk_t v)
{
- return parse_cert(cfg, AUTH_RULE_CA_CERT, v);
+ return parse_cert(auth, AUTH_RULE_CA_CERT, v);
}
/**
@@ -1234,6 +1250,7 @@ CALLBACK(child_kv, bool,
{ "updown", parse_string, &child->updown },
{ "hostaccess", parse_bool, &child->hostaccess },
{ "mode", parse_mode, &child->mode },
+ { "policies", parse_bool, &child->policies },
{ "replay_window", parse_uint32, &child->replay_window },
{ "rekey_time", parse_time, &child->lft.time.rekey },
{ "life_time", parse_time, &child->lft.time.life },
@@ -1264,8 +1281,8 @@ CALLBACK(auth_li, bool,
{
parse_rule_t rules[] = {
{ "groups", parse_group, auth->cfg },
- { "certs", parse_certs, auth->cfg },
- { "cacerts", parse_cacerts, auth->cfg },
+ { "certs", parse_certs, auth },
+ { "cacerts", parse_cacerts, auth },
};
return parse_rules(rules, countof(rules), name, value,
@@ -1341,6 +1358,7 @@ CALLBACK(children_sn, bool,
.local_ts = linked_list_create(),
.remote_ts = linked_list_create(),
.mode = MODE_TUNNEL,
+ .policies = TRUE,
.replay_window = REPLAY_UNDEFINED,
.dpd_action = ACTION_NONE,
.start_action = ACTION_NONE,
@@ -1352,10 +1370,12 @@ CALLBACK(children_sn, bool,
.jitter = LFT_UNDEFINED,
},
.bytes = {
+ .rekey = LFT_UNDEFINED,
.life = LFT_UNDEFINED,
.jitter = LFT_UNDEFINED,
},
.packets = {
+ .rekey = LFT_UNDEFINED,
.life = LFT_UNDEFINED,
.jitter = LFT_UNDEFINED,
},
@@ -1408,6 +1428,15 @@ CALLBACK(children_sn, bool,
{
child.lft.packets.life = child.lft.packets.rekey * 110 / 100;
}
+ /* if no soft lifetime specified, add one at hard lifetime - 10% */
+ if (child.lft.bytes.rekey == LFT_UNDEFINED)
+ {
+ child.lft.bytes.rekey = child.lft.bytes.life * 90 / 100;
+ }
+ if (child.lft.packets.rekey == LFT_UNDEFINED)
+ {
+ child.lft.packets.rekey = child.lft.packets.life * 90 / 100;
+ }
/* if no rand time defined, use difference of hard and soft */
if (child.lft.time.jitter == LFT_UNDEFINED)
{
@@ -1433,6 +1462,8 @@ CALLBACK(children_sn, bool,
child.inactivity, child.reqid, &child.mark_in,
&child.mark_out, child.tfc);
+ cfg->set_mipv6_options(cfg, FALSE, child.policies);
+
if (child.replay_window != REPLAY_UNDEFINED)
{
cfg->set_replay_window(cfg, child.replay_window);
@@ -1558,7 +1589,7 @@ static void run_start_action(private_vici_config_t *this, peer_cfg_t *peer_cfg,
DBG1(DBG_CFG, "initiating '%s'", child_cfg->get_name(child_cfg));
charon->controller->initiate(charon->controller,
peer_cfg->get_ref(peer_cfg), child_cfg->get_ref(child_cfg),
- NULL, NULL, 0);
+ NULL, NULL, 0, FALSE);
break;
case ACTION_ROUTE:
DBG1(DBG_CFG, "installing '%s'", child_cfg->get_name(child_cfg));
@@ -1958,20 +1989,20 @@ CALLBACK(unload_conn, vici_message_t*,
{
enumerator_t *enumerator;
peer_cfg_t *cfg;
+ char *conn_name;
bool found = FALSE;
- char *conn;
- conn = message->get_str(message, NULL, "name");
- if (!conn)
+ conn_name = message->get_str(message, NULL, "name");
+ if (!conn_name)
{
- return create_reply("missing connection name to unload");
+ return create_reply("unload: missing connection name");
}
this->lock->write_lock(this->lock);
enumerator = this->conns->create_enumerator(this->conns);
while (enumerator->enumerate(enumerator, &cfg))
{
- if (streq(cfg->get_name(cfg), conn))
+ if (streq(cfg->get_name(cfg), conn_name))
{
this->conns->remove_at(this->conns, enumerator);
cfg->destroy(cfg);
@@ -1984,7 +2015,7 @@ CALLBACK(unload_conn, vici_message_t*,
if (!found)
{
- return create_reply("connection '%s' not found for unloading", conn);
+ return create_reply("unload: connection '%s' not found", conn_name);
}
return create_reply(NULL);
}
@@ -2042,7 +2073,8 @@ METHOD(vici_config_t, destroy, void,
/**
* See header
*/
-vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher)
+vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher,
+ vici_authority_t *authority)
{
private_vici_config_t *this;
@@ -2058,6 +2090,7 @@ vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher)
.dispatcher = dispatcher,
.conns = linked_list_create(),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ .authority = authority,
);
manage_commands(this, TRUE);
diff --git a/src/libcharon/plugins/vici/vici_config.h b/src/libcharon/plugins/vici/vici_config.h
index 820d5f300..c3245bf5c 100644
--- a/src/libcharon/plugins/vici/vici_config.h
+++ b/src/libcharon/plugins/vici/vici_config.h
@@ -2,6 +2,9 @@
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
@@ -22,6 +25,7 @@
#define VICI_CONFIG_H_
#include "vici_dispatcher.h"
+#include "vici_authority.h"
#include <config/backend.h>
@@ -46,8 +50,10 @@ struct vici_config_t {
* Create a vici_config instance.
*
* @param dispatcher dispatcher to receive requests from
+ * @param authority Auxiliary certification authority information
* @return config backend
*/
-vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher);
+vici_config_t *vici_config_create(vici_dispatcher_t *dispatcher,
+ vici_authority_t *authority);
#endif /** VICI_CONFIG_H_ @}*/
diff --git a/src/libcharon/plugins/vici/vici_control.c b/src/libcharon/plugins/vici/vici_control.c
index 01d503644..752007c24 100644
--- a/src/libcharon/plugins/vici/vici_control.c
+++ b/src/libcharon/plugins/vici/vici_control.c
@@ -138,7 +138,7 @@ static child_cfg_t* find_child_cfg(char *name, peer_cfg_t **out)
{
enumerator_t *enumerator;
peer_cfg_t *peer_cfg;
- child_cfg_t *child_cfg;
+ child_cfg_t *child_cfg = NULL;
enumerator = charon->backends->create_peer_cfg_enumerator(
charon->backends, NULL, NULL, NULL, NULL, IKE_ANY);
@@ -163,6 +163,7 @@ CALLBACK(initiate, vici_message_t*,
peer_cfg_t *peer_cfg;
char *child;
u_int timeout;
+ bool limits;
log_info_t log = {
.dispatcher = this->dispatcher,
.id = id,
@@ -170,6 +171,7 @@ CALLBACK(initiate, vici_message_t*,
child = request->get_str(request, NULL, "child");
timeout = request->get_int(request, 0, "timeout");
+ limits = request->get_bool(request, FALSE, "init-limits");
log.level = request->get_int(request, 1, "loglevel");
if (!child)
@@ -184,14 +186,17 @@ CALLBACK(initiate, vici_message_t*,
{
return send_reply(this, "CHILD_SA config '%s' not found", child);
}
- switch (charon->controller->initiate(charon->controller,
- peer_cfg, child_cfg, (controller_cb_t)log_vici, &log, timeout))
+ switch (charon->controller->initiate(charon->controller, peer_cfg,
+ child_cfg, (controller_cb_t)log_vici, &log, timeout, limits))
{
case SUCCESS:
return send_reply(this, NULL);
case OUT_OF_RES:
return send_reply(this, "CHILD_SA '%s' not established after %dms",
child, timeout);
+ case INVALID_STATE:
+ return send_reply(this, "establishing CHILD_SA '%s' not possible "
+ "at the moment due to limits", child);
case FAILED:
default:
return send_reply(this, "establishing CHILD_SA '%s' failed", child);
diff --git a/src/libcharon/plugins/vici/vici_cred.c b/src/libcharon/plugins/vici/vici_cred.c
index d4c02de6d..ffdc034ea 100644
--- a/src/libcharon/plugins/vici/vici_cred.c
+++ b/src/libcharon/plugins/vici/vici_cred.c
@@ -294,6 +294,12 @@ static void manage_commands(private_vici_cred_t *this, bool reg)
manage_command(this, "load-shared", load_shared, reg);
}
+METHOD(vici_cred_t, add_cert, certificate_t*,
+ private_vici_cred_t *this, certificate_t *cert)
+{
+ return this->creds->get_cert_ref(this->creds, cert);
+}
+
METHOD(vici_cred_t, destroy, void,
private_vici_cred_t *this)
{
@@ -313,6 +319,7 @@ vici_cred_t *vici_cred_create(vici_dispatcher_t *dispatcher)
INIT(this,
.public = {
+ .add_cert = _add_cert,
.destroy = _destroy,
},
.dispatcher = dispatcher,
diff --git a/src/libcharon/plugins/vici/vici_cred.h b/src/libcharon/plugins/vici/vici_cred.h
index e109a27da..8359c0e88 100644
--- a/src/libcharon/plugins/vici/vici_cred.h
+++ b/src/libcharon/plugins/vici/vici_cred.h
@@ -31,6 +31,14 @@ typedef struct vici_cred_t vici_cred_t;
struct vici_cred_t {
/**
+ * Add a certificate to the certificate store
+ *
+ * @param cert certificate to be added to store
+ * @return reference to certificate or cached copy
+ */
+ certificate_t* (*add_cert)(vici_cred_t *this, certificate_t *cert);
+
+ /**
* Destroy a vici_cred_t.
*/
void (*destroy)(vici_cred_t *this);
diff --git a/src/libcharon/plugins/vici/vici_logger.c b/src/libcharon/plugins/vici/vici_logger.c
index cffd65bad..6d3584ebd 100644
--- a/src/libcharon/plugins/vici/vici_logger.c
+++ b/src/libcharon/plugins/vici/vici_logger.c
@@ -18,6 +18,7 @@
#include <daemon.h>
#include <threading/mutex.h>
+#include <processing/jobs/callback_job.h>
typedef struct private_vici_logger_t private_vici_logger_t;
@@ -42,11 +43,54 @@ struct private_vici_logger_t {
int recursive;
/**
+ * List of messages to raise async events
+ */
+ linked_list_t *queue;
+
+ /**
* Mutex to synchronize logging
*/
mutex_t *mutex;
};
+/**
+ * Async callback to raise events for queued messages
+ */
+static job_requeue_t raise_events(private_vici_logger_t *this)
+{
+ vici_message_t *message;
+ u_int count;
+
+ this->mutex->lock(this->mutex);
+ count = this->queue->get_count(this->queue);
+ this->queue->remove_first(this->queue, (void**)&message);
+ this->mutex->unlock(this->mutex);
+
+ if (count > 0)
+ {
+ this->dispatcher->raise_event(this->dispatcher, "log", 0, message);
+ }
+ if (count > 1)
+ {
+ return JOB_REQUEUE_DIRECT;
+ }
+ return JOB_REQUEUE_NONE;
+}
+
+/**
+ * Queue a message for async processing
+ */
+static void queue_messsage(private_vici_logger_t *this, vici_message_t *message)
+{
+ this->queue->insert_last(this->queue, message);
+ if (this->queue->get_count(this->queue) == 1)
+ {
+ lib->processor->queue_job(lib->processor, (job_t*)
+ callback_job_create((callback_job_cb_t)raise_events,
+ this, NULL, NULL));
+ }
+}
+
METHOD(logger_t, log_, void,
private_vici_logger_t *this, debug_t group, level_t level, int thread,
ike_sa_t* ike_sa, const char *msg)
@@ -75,7 +119,7 @@ METHOD(logger_t, log_, void,
message = builder->finalize(builder);
if (message)
{
- this->dispatcher->raise_event(this->dispatcher, "log", 0, message);
+ queue_messsage(this, message);
}
}
this->recursive--;
@@ -101,6 +145,7 @@ METHOD(vici_logger_t, destroy, void,
private_vici_logger_t *this)
{
manage_commands(this, FALSE);
+ this->queue->destroy_offset(this->queue, offsetof(vici_message_t, destroy));
this->mutex->destroy(this->mutex);
free(this);
}
@@ -121,6 +166,7 @@ vici_logger_t *vici_logger_create(vici_dispatcher_t *dispatcher)
.destroy = _destroy,
},
.dispatcher = dispatcher,
+ .queue = linked_list_create(),
.mutex = mutex_create(MUTEX_TYPE_RECURSIVE),
);
diff --git a/src/libcharon/plugins/vici/vici_message.c b/src/libcharon/plugins/vici/vici_message.c
index e79fbc8d3..fb6e8a1ab 100644
--- a/src/libcharon/plugins/vici/vici_message.c
+++ b/src/libcharon/plugins/vici/vici_message.c
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
@@ -385,6 +388,41 @@ METHOD(vici_message_t, get_int, int,
return val;
}
+METHOD(vici_message_t, vget_bool, bool,
+ private_vici_message_t *this, bool def, char *fmt, va_list args)
+{
+ chunk_t value;
+ bool found;
+ char buf[16];
+
+ 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);
+ return settings_value_as_bool(buf, def);
+ }
+ }
+ return def;
+}
+
+METHOD(vici_message_t, get_bool, bool,
+ private_vici_message_t *this, bool def, char *fmt, ...)
+{
+ va_list args;
+ bool val;
+
+ va_start(args, fmt);
+ val = vget_bool(this, def, fmt, args);
+ va_end(args);
+ return val;
+}
+
METHOD(vici_message_t, vget_value, chunk_t,
private_vici_message_t *this, chunk_t def, char *fmt, va_list args)
{
@@ -633,6 +671,8 @@ vici_message_t *vici_message_create_from_data(chunk_t data, bool cleanup)
.vget_str = _vget_str,
.get_int = _get_int,
.vget_int = _vget_int,
+ .get_bool = _get_bool,
+ .vget_bool = _vget_bool,
.get_value = _get_value,
.vget_value = _vget_value,
.get_encoding = _get_encoding,
diff --git a/src/libcharon/plugins/vici/vici_message.h b/src/libcharon/plugins/vici/vici_message.h
index 1a89cf829..d47e7a0f9 100644
--- a/src/libcharon/plugins/vici/vici_message.h
+++ b/src/libcharon/plugins/vici/vici_message.h
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
@@ -15,7 +18,7 @@
/**
* @defgroup vici_message vici_message
- * @{ @ingroup vici_dispatcher
+ * @{ @ingroup vici
*/
#ifndef VICI_MESSAGE_H_
@@ -138,6 +141,26 @@ struct vici_message_t {
int (*vget_int)(vici_message_t *this, int def, char *fmt, va_list args);
/**
+ * Get the value of a key/value pair as boolean.
+ *
+ * @param def default value if not found
+ * @param fmt printf style format string for key, with sections
+ * @param ... arguments to fmt string
+ * @return value
+ */
+ bool (*get_bool)(vici_message_t *this, bool def, char *fmt, ...);
+
+ /**
+ * Get the value of a key/value pair as boolean, va_list variant
+ *
+ * @param def default value if not found
+ * @param fmt printf style format string for key, with sections
+ * @param args arguments to fmt string
+ * @return value
+ */
+ bool (*vget_bool)(vici_message_t *this, bool def, char *fmt, va_list args);
+
+ /**
* Get the raw value of a key/value pair.
*
* @param def default value if not found
diff --git a/src/libcharon/plugins/vici/vici_plugin.c b/src/libcharon/plugins/vici/vici_plugin.c
index 7ae58a317..53ed8cdfb 100644
--- a/src/libcharon/plugins/vici/vici_plugin.c
+++ b/src/libcharon/plugins/vici/vici_plugin.c
@@ -2,6 +2,9 @@
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
@@ -42,6 +45,7 @@
#include "vici_cred.h"
#include "vici_config.h"
#include "vici_attribute.h"
+#include "vici_authority.h"
#include "vici_logger.h"
#include <library.h>
@@ -80,6 +84,11 @@ struct private_vici_plugin_t {
vici_cred_t *cred;
/**
+ * Certification Authority backend
+ */
+ vici_authority_t *authority;
+
+ /**
* Configuration backend
*/
vici_config_t *config;
@@ -119,7 +128,10 @@ static bool register_vici(private_vici_plugin_t *this,
this->query = vici_query_create(this->dispatcher);
this->control = vici_control_create(this->dispatcher);
this->cred = vici_cred_create(this->dispatcher);
- this->config = vici_config_create(this->dispatcher);
+ this->authority = vici_authority_create(this->dispatcher,
+ this->cred);
+ lib->credmgr->add_set(lib->credmgr, &this->authority->set);
+ this->config = vici_config_create(this->dispatcher, this->authority);
this->attrs = vici_attribute_create(this->dispatcher);
this->logger = vici_logger_create(this->dispatcher);
@@ -145,6 +157,8 @@ static bool register_vici(private_vici_plugin_t *this,
this->logger->destroy(this->logger);
this->attrs->destroy(this->attrs);
this->config->destroy(this->config);
+ lib->credmgr->remove_set(lib->credmgr, &this->authority->set);
+ this->authority->destroy(this->authority);
this->cred->destroy(this->cred);
this->control->destroy(this->control);
this->query->destroy(this->query);
diff --git a/src/libcharon/plugins/vici/vici_query.c b/src/libcharon/plugins/vici/vici_query.c
index d94d760b9..98d264fca 100644
--- a/src/libcharon/plugins/vici/vici_query.c
+++ b/src/libcharon/plugins/vici/vici_query.c
@@ -929,7 +929,7 @@ CALLBACK(stats, vici_message_t*,
charon->ike_sa_manager->get_count(charon->ike_sa_manager));
b->add_kv(b, "half-open", "%u",
charon->ike_sa_manager->get_half_open_count(charon->ike_sa_manager,
- NULL));
+ NULL, FALSE));
b->end_section(b);
b->begin_list(b, "plugins");
@@ -1031,7 +1031,9 @@ static void manage_commands(private_vici_query_t *this, bool reg)
this->dispatcher->manage_event(this->dispatcher, "list-conn", reg);
this->dispatcher->manage_event(this->dispatcher, "list-cert", reg);
this->dispatcher->manage_event(this->dispatcher, "ike-updown", reg);
+ this->dispatcher->manage_event(this->dispatcher, "ike-rekey", reg);
this->dispatcher->manage_event(this->dispatcher, "child-updown", reg);
+ this->dispatcher->manage_event(this->dispatcher, "child-rekey", reg);
manage_command(this, "list-sas", list_sas, reg);
manage_command(this, "list-policies", list_policies, reg);
manage_command(this, "list-conns", list_conns, reg);
@@ -1054,10 +1056,14 @@ METHOD(listener_t, ike_updown, bool,
now = time_monotonic(NULL);
b = vici_builder_create();
+
+ if (up)
+ {
+ b->add_kv(b, "up", "yes");
+ }
+
b->begin_section(b, ike_sa->get_name(ike_sa));
list_ike(this, b, ike_sa, now);
- b->begin_section(b, "child-sas");
- b->end_section(b);
b->end_section(b);
this->dispatcher->raise_event(this->dispatcher,
@@ -1066,6 +1072,35 @@ METHOD(listener_t, ike_updown, bool,
return TRUE;
}
+METHOD(listener_t, ike_rekey, bool,
+ private_vici_query_t *this, ike_sa_t *old, ike_sa_t *new)
+{
+ vici_builder_t *b;
+ time_t now;
+
+ if (!this->dispatcher->has_event_listeners(this->dispatcher, "ike-rekey"))
+ {
+ return TRUE;
+ }
+
+ now = time_monotonic(NULL);
+
+ b = vici_builder_create();
+ b->begin_section(b, old->get_name(old));
+ b->begin_section(b, "old");
+ list_ike(this, b, old, now);
+ b->end_section(b);
+ b->begin_section(b, "new");
+ list_ike(this, b, new, now);
+ b->end_section(b);
+ b->end_section(b);
+
+ this->dispatcher->raise_event(this->dispatcher,
+ "ike-rekey", 0, b->finalize(b));
+
+ return TRUE;
+}
+
METHOD(listener_t, child_updown, bool,
private_vici_query_t *this, ike_sa_t *ike_sa, child_sa_t *child_sa, bool up)
{
@@ -1080,6 +1115,11 @@ METHOD(listener_t, child_updown, bool,
now = time_monotonic(NULL);
b = vici_builder_create();
+ if (up)
+ {
+ b->add_kv(b, "up", "yes");
+ }
+
b->begin_section(b, ike_sa->get_name(ike_sa));
list_ike(this, b, ike_sa, now);
b->begin_section(b, "child-sas");
@@ -1097,6 +1137,45 @@ METHOD(listener_t, child_updown, bool,
return TRUE;
}
+METHOD(listener_t, child_rekey, bool,
+ private_vici_query_t *this, ike_sa_t *ike_sa, child_sa_t *old,
+ child_sa_t *new)
+{
+ vici_builder_t *b;
+ time_t now;
+
+ if (!this->dispatcher->has_event_listeners(this->dispatcher, "child-rekey"))
+ {
+ return TRUE;
+ }
+
+ now = time_monotonic(NULL);
+ b = vici_builder_create();
+
+ b->begin_section(b, ike_sa->get_name(ike_sa));
+ list_ike(this, b, ike_sa, now);
+ b->begin_section(b, "child-sas");
+
+ b->begin_section(b, old->get_name(old));
+
+ b->begin_section(b, "old");
+ list_child(this, b, old, now);
+ b->end_section(b);
+ b->begin_section(b, "new");
+ list_child(this, b, new, now);
+ b->end_section(b);
+
+ b->end_section(b);
+
+ b->end_section(b);
+ b->end_section(b);
+
+ this->dispatcher->raise_event(this->dispatcher,
+ "child-rekey", 0, b->finalize(b));
+
+ return TRUE;
+}
+
METHOD(vici_query_t, destroy, void,
private_vici_query_t *this)
{
@@ -1115,7 +1194,9 @@ vici_query_t *vici_query_create(vici_dispatcher_t *dispatcher)
.public = {
.listener = {
.ike_updown = _ike_updown,
+ .ike_rekey = _ike_rekey,
.child_updown = _child_updown,
+ .child_rekey = _child_rekey,
},
.destroy = _destroy,
},
diff --git a/src/libcharon/plugins/whitelist/whitelist_listener.c b/src/libcharon/plugins/whitelist/whitelist_listener.c
index d0357b410..7e5b2f4e0 100644
--- a/src/libcharon/plugins/whitelist/whitelist_listener.c
+++ b/src/libcharon/plugins/whitelist/whitelist_listener.c
@@ -52,7 +52,7 @@ struct private_whitelist_listener_t {
*/
static u_int hash(identification_t *key)
{
- return chunk_hash(key->get_encoding(key));
+ return key->hash(key, 0);
}
/**
diff --git a/src/libcharon/processing/jobs/initiate_mediation_job.c b/src/libcharon/processing/jobs/initiate_mediation_job.c
index 17ab83053..5b5fb9d98 100644
--- a/src/libcharon/processing/jobs/initiate_mediation_job.c
+++ b/src/libcharon/processing/jobs/initiate_mediation_job.c
@@ -119,8 +119,8 @@ METHOD(job_t, initiate, job_requeue_t,
/* we need an additional reference because initiate consumes one */
mediation_cfg->get_ref(mediation_cfg);
- if (charon->controller->initiate(charon->controller, mediation_cfg,
- NULL, (controller_cb_t)initiate_callback, this, 0) != SUCCESS)
+ if (charon->controller->initiate(charon->controller, mediation_cfg, NULL,
+ (controller_cb_t)initiate_callback, this, 0, FALSE) != SUCCESS)
{
mediation_cfg->destroy(mediation_cfg);
mediated_cfg->destroy(mediated_cfg);
diff --git a/src/libcharon/processing/jobs/process_message_job.c b/src/libcharon/processing/jobs/process_message_job.c
index a6795e766..31f048db6 100644
--- a/src/libcharon/processing/jobs/process_message_job.c
+++ b/src/libcharon/processing/jobs/process_message_job.c
@@ -91,16 +91,26 @@ METHOD(job_t, get_priority, job_priority_t,
{
case IKE_AUTH:
/* IKE auth is rather expensive and often blocking, low priority */
+ case AGGRESSIVE:
+ case ID_PROT:
+ /* AM is basically IKE_SA_INIT/IKE_AUTH combined (without EAP/XAuth)
+ * MM is similar, but stretched out more */
return JOB_PRIO_LOW;
case INFORMATIONAL:
+ case INFORMATIONAL_V1:
/* INFORMATIONALs are inexpensive, for DPD we should have low
* reaction times */
return JOB_PRIO_HIGH;
case IKE_SA_INIT:
- case CREATE_CHILD_SA:
- default:
/* IKE_SA_INIT is expensive, but we will drop them in the receiver
* if we are overloaded */
+ case CREATE_CHILD_SA:
+ case QUICK_MODE:
+ /* these may require DH, but if not they are relatively cheap */
+ case TRANSACTION:
+ /* these are mostly cheap, however, if XAuth via RADIUS is used
+ * they may block */
+ default:
return JOB_PRIO_MEDIUM;
}
}
diff --git a/src/libcharon/processing/jobs/rekey_child_sa_job.c b/src/libcharon/processing/jobs/rekey_child_sa_job.c
index 8f17d39ab..057876b33 100644
--- a/src/libcharon/processing/jobs/rekey_child_sa_job.c
+++ b/src/libcharon/processing/jobs/rekey_child_sa_job.c
@@ -67,7 +67,10 @@ METHOD(job_t, execute, job_requeue_t,
}
else
{
- ike_sa->rekey_child_sa(ike_sa, this->protocol, this->spi);
+ if (ike_sa->get_state(ike_sa) != IKE_PASSIVE)
+ {
+ ike_sa->rekey_child_sa(ike_sa, this->protocol, this->spi);
+ }
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
return JOB_REQUEUE_NONE;
diff --git a/src/libcharon/processing/jobs/start_action_job.c b/src/libcharon/processing/jobs/start_action_job.c
index 981473b5c..5e88ac230 100644
--- a/src/libcharon/processing/jobs/start_action_job.c
+++ b/src/libcharon/processing/jobs/start_action_job.c
@@ -61,7 +61,7 @@ METHOD(job_t, execute, job_requeue_t,
charon->controller->initiate(charon->controller,
peer_cfg->get_ref(peer_cfg),
child_cfg->get_ref(child_cfg),
- NULL, NULL, 0);
+ NULL, NULL, 0, FALSE);
break;
case ACTION_ROUTE:
DBG1(DBG_JOB, "start action: route '%s'", name);
diff --git a/src/libcharon/sa/child_sa.c b/src/libcharon/sa/child_sa.c
index 94cf07c33..73f2ec9d3 100644
--- a/src/libcharon/sa/child_sa.c
+++ b/src/libcharon/sa/child_sa.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2011 Tobias Brunner
+ * Copyright (C) 2006-2015 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005 Jan Hutter
@@ -106,6 +106,11 @@ struct private_child_sa_t {
*/
bool reqid_allocated;
+ /**
+ * Is the reqid statically configured
+ */
+ bool static_reqid;
+
/*
* Unique CHILD_SA identifier
*/
@@ -698,7 +703,7 @@ METHOD(child_sa_t, install, status_t,
this->proposal->get_algorithm(this->proposal, EXTENDED_SEQUENCE_NUMBERS,
&esn, NULL);
- if (!this->reqid_allocated && !this->reqid)
+ if (!this->reqid_allocated && !this->static_reqid)
{
status = hydra->kernel_interface->alloc_reqid(hydra->kernel_interface,
my_ts, other_ts, this->mark_in, this->mark_out,
@@ -826,7 +831,7 @@ METHOD(child_sa_t, add_policies, status_t,
traffic_selector_t *my_ts, *other_ts;
status_t status = SUCCESS;
- if (!this->reqid_allocated && !this->reqid)
+ if (!this->reqid_allocated && !this->static_reqid)
{
/* trap policy, get or confirm reqid */
status = hydra->kernel_interface->alloc_reqid(
@@ -1305,6 +1310,10 @@ child_sa_t * child_sa_create(host_t *me, host_t* other,
this->reqid = charon->traps->find_reqid(charon->traps, config);
}
}
+ else
+ {
+ this->static_reqid = TRUE;
+ }
/* MIPv6 proxy transport mode sets SA endpoints to TS hosts */
if (config->get_mode(config) == MODE_TRANSPORT &&
diff --git a/src/libcharon/sa/eap/eap_method.c b/src/libcharon/sa/eap/eap_method.c
index a05e8c59a..9ce6ecf00 100644
--- a/src/libcharon/sa/eap/eap_method.c
+++ b/src/libcharon/sa/eap/eap_method.c
@@ -30,7 +30,8 @@ bool eap_method_register(plugin_t *plugin, plugin_feature_t *feature,
{
if (reg)
{
- charon->eap->add_method(charon->eap, feature->arg.eap, 0,
+ charon->eap->add_method(charon->eap, feature->arg.eap.type,
+ feature->arg.eap.vendor,
feature->type == FEATURE_EAP_SERVER ? EAP_SERVER : EAP_PEER,
(eap_constructor_t)data);
}
diff --git a/src/libcharon/sa/ike_sa.c b/src/libcharon/sa/ike_sa.c
index 3aafa4c13..dcf9d5f2c 100644
--- a/src/libcharon/sa/ike_sa.c
+++ b/src/libcharon/sa/ike_sa.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006-2014 Tobias Brunner
+ * Copyright (C) 2006-2015 Tobias Brunner
* Copyright (C) 2006 Daniel Roethlisberger
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
@@ -487,8 +487,9 @@ METHOD(ike_sa_t, send_keepalive, void,
send_keepalive_job_t *job;
time_t last_out, now, diff;
- if (!(this->conditions & COND_NAT_HERE) || this->keepalive_interval == 0)
- { /* disable keep alives if we are not NATed anymore */
+ if (!(this->conditions & COND_NAT_HERE) || this->keepalive_interval == 0 ||
+ this->state == IKE_PASSIVE)
+ { /* disable keep alives if we are not NATed anymore, or we are passive */
return;
}
@@ -651,7 +652,7 @@ METHOD(ike_sa_t, get_state, ike_sa_state_t,
METHOD(ike_sa_t, set_state, void,
private_ike_sa_t *this, ike_sa_state_t state)
{
- bool trigger_dpd = FALSE;
+ bool trigger_dpd = FALSE, keepalives = FALSE;
DBG2(DBG_IKE, "IKE_SA %s[%d] state change: %N => %N",
get_name(this), this->unique_id,
@@ -722,6 +723,10 @@ METHOD(ike_sa_t, set_state, void,
* so yet, so prevent that. */
this->stats[STAT_INBOUND] = this->stats[STAT_ESTABLISHED];
}
+ if (this->state == IKE_PASSIVE)
+ {
+ keepalives = TRUE;
+ }
}
break;
}
@@ -742,6 +747,10 @@ METHOD(ike_sa_t, set_state, void,
DBG1(DBG_IKE, "DPD not supported by peer, disabled");
}
}
+ if (keepalives)
+ {
+ send_keepalive(this);
+ }
}
METHOD(ike_sa_t, reset, void,
@@ -1200,6 +1209,19 @@ static void resolve_hosts(private_ike_sa_t *this)
break;
}
+ /* if an IP address is set locally, use the same family to resolve remote */
+ if (family == AF_UNSPEC && !this->remote_host)
+ {
+ if (this->local_host)
+ {
+ family = this->local_host->get_family(this->local_host);
+ }
+ else
+ {
+ family = ike_cfg_get_family(this->ike_cfg, TRUE);
+ }
+ }
+
if (this->remote_host)
{
host = this->remote_host->clone(this->remote_host);
@@ -1211,7 +1233,18 @@ static void resolve_hosts(private_ike_sa_t *this)
}
if (host)
{
- set_other_host(this, host);
+ if (!host->is_anyaddr(host) ||
+ this->other_host->is_anyaddr(this->other_host))
+ { /* don't set to %any if we currently have an address, but the
+ * address family might have changed */
+ set_other_host(this, host);
+ }
+ else
+ { /* reuse the original port as some implementations might not like
+ * initial IKE messages on other ports */
+ this->other_host->set_port(this->other_host, host->get_port(host));
+ host->destroy(host);
+ }
}
if (this->local_host)
diff --git a/src/libcharon/sa/ike_sa_id.c b/src/libcharon/sa/ike_sa_id.c
index 0f0f1ab63..e52086483 100644
--- a/src/libcharon/sa/ike_sa_id.c
+++ b/src/libcharon/sa/ike_sa_id.c
@@ -18,7 +18,7 @@
#include "ike_sa_id.h"
#include <stdio.h>
-
+#include <encoding/payloads/ike_header.h>
typedef struct private_ike_sa_id_t private_ike_sa_id_t;
@@ -90,6 +90,8 @@ METHOD(ike_sa_id_t, equals, bool,
return FALSE;
}
return this->ike_version == other->ike_version &&
+ (this->ike_version == IKEV1_MAJOR_VERSION ||
+ this->is_initiator_flag == other->is_initiator_flag) &&
this->initiator_spi == other->initiator_spi &&
this->responder_spi == other->responder_spi;
}
diff --git a/src/libcharon/sa/ike_sa_manager.c b/src/libcharon/sa/ike_sa_manager.c
index 938f7848f..37d69874d 100644
--- a/src/libcharon/sa/ike_sa_manager.c
+++ b/src/libcharon/sa/ike_sa_manager.c
@@ -1,7 +1,7 @@
/*
* Copyright (C) 2005-2011 Martin Willi
* Copyright (C) 2011 revosec AG
- * Copyright (C) 2008-2012 Tobias Brunner
+ * Copyright (C) 2008-2015 Tobias Brunner
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
*
@@ -157,6 +157,8 @@ static bool entry_match_by_id(entry_t *entry, ike_sa_id_t *id)
}
if ((id->get_responder_spi(id) == 0 ||
entry->ike_sa_id->get_responder_spi(entry->ike_sa_id) == 0) &&
+ (id->get_ike_version(id) == IKEV1_MAJOR_VERSION ||
+ id->is_initiator(id) == entry->ike_sa_id->is_initiator(entry->ike_sa_id)) &&
id->get_initiator_spi(id) == entry->ike_sa_id->get_initiator_spi(entry->ike_sa_id))
{
/* this is TRUE for IKE_SAs that we initiated but have not yet received a response */
@@ -204,6 +206,9 @@ struct half_open_t {
/** the number of half-open IKE_SAs with that host */
u_int count;
+
+ /** the number of half-open IKE_SAs we responded to with that host */
+ u_int count_responder;
};
/**
@@ -359,6 +364,11 @@ struct private_ike_sa_manager_t {
refcount_t half_open_count;
/**
+ * Total number of half-open IKE_SAs as responder.
+ */
+ refcount_t half_open_count_responder;
+
+ /**
* Hash table with connected_peers_t objects.
*/
table_item_t **connected_peers_table;
@@ -384,6 +394,11 @@ struct private_ike_sa_manager_t {
rng_t *rng;
/**
+ * Lock to access the RNG instance
+ */
+ rwlock_t *rng_lock;
+
+ /**
* reuse existing IKE_SAs in checkout_by_config
*/
bool reuse_ikesa;
@@ -730,9 +745,11 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
table_item_t *item;
u_int row, segment;
rwlock_t *lock;
+ ike_sa_id_t *ike_id;
half_open_t *half_open;
chunk_t addr;
+ ike_id = entry->ike_sa_id;
addr = entry->other->get_address(entry->other);
row = chunk_hash(addr) & this->table_mask;
segment = row & this->segment_mask;
@@ -745,7 +762,6 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
if (chunk_equals(addr, half_open->other))
{
- half_open->count++;
break;
}
item = item->next;
@@ -755,7 +771,6 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
{
INIT(half_open,
.other = chunk_clone(addr),
- .count = 1,
);
INIT(item,
.value = half_open,
@@ -763,8 +778,14 @@ static void put_half_open(private_ike_sa_manager_t *this, entry_t *entry)
);
this->half_open_table[row] = item;
}
- this->half_open_segments[segment].count++;
+ half_open->count++;
ref_get(&this->half_open_count);
+ if (!ike_id->is_initiator(ike_id))
+ {
+ half_open->count_responder++;
+ ref_get(&this->half_open_count_responder);
+ }
+ this->half_open_segments[segment].count++;
lock->unlock(lock);
}
@@ -776,8 +797,10 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
table_item_t *item, *prev = NULL;
u_int row, segment;
rwlock_t *lock;
+ ike_sa_id_t *ike_id;
chunk_t addr;
+ ike_id = entry->ike_sa_id;
addr = entry->other->get_address(entry->other);
row = chunk_hash(addr) & this->table_mask;
segment = row & this->segment_mask;
@@ -790,6 +813,12 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
if (chunk_equals(addr, half_open->other))
{
+ if (!ike_id->is_initiator(ike_id))
+ {
+ half_open->count_responder--;
+ ignore_result(ref_put(&this->half_open_count_responder));
+ }
+ ignore_result(ref_put(&this->half_open_count));
if (--half_open->count == 0)
{
if (prev)
@@ -804,7 +833,6 @@ static void remove_half_open(private_ike_sa_manager_t *this, entry_t *entry)
free(item);
}
this->half_open_segments[segment].count--;
- ignore_result(ref_put(&this->half_open_count));
break;
}
prev = item;
@@ -943,12 +971,14 @@ static u_int64_t get_spi(private_ike_sa_manager_t *this)
{
u_int64_t spi;
- if (this->rng &&
- this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi))
+ this->rng_lock->read_lock(this->rng_lock);
+ if (!this->rng ||
+ !this->rng->get_bytes(this->rng, sizeof(spi), (u_int8_t*)&spi))
{
- return spi;
+ spi = 0;
}
- return 0;
+ this->rng_lock->unlock(this->rng_lock);
+ return spi;
}
/**
@@ -1563,7 +1593,6 @@ METHOD(ike_sa_manager_t, checkin, void,
put_half_open(this, entry);
}
else if (!entry->half_open &&
- !entry->ike_sa_id->is_initiator(entry->ike_sa_id) &&
ike_sa->get_state(ike_sa) == IKE_CONNECTING)
{
/* this is a new half-open SA */
@@ -1579,6 +1608,12 @@ METHOD(ike_sa_manager_t, checkin, void,
entry = entry_create();
entry->ike_sa_id = ike_sa_id->clone(ike_sa_id);
entry->ike_sa = ike_sa;
+ if (ike_sa->get_state(ike_sa) == IKE_CONNECTING)
+ {
+ entry->half_open = TRUE;
+ entry->other = other->clone(other);
+ put_half_open(this, entry);
+ }
segment = put_entry(this, entry);
}
@@ -1937,7 +1972,7 @@ METHOD(ike_sa_manager_t, get_count, u_int,
}
METHOD(ike_sa_manager_t, get_half_open_count, u_int,
- private_ike_sa_manager_t *this, host_t *ip)
+ private_ike_sa_manager_t *this, host_t *ip, bool responder_only)
{
table_item_t *item;
u_int row, segment;
@@ -1959,7 +1994,8 @@ METHOD(ike_sa_manager_t, get_half_open_count, u_int,
if (chunk_equals(addr, half_open->other))
{
- count = half_open->count;
+ count = responder_only ? half_open->count_responder
+ : half_open->count;
break;
}
item = item->next;
@@ -1968,7 +2004,8 @@ METHOD(ike_sa_manager_t, get_half_open_count, u_int,
}
else
{
- count = (u_int)ref_cur(&this->half_open_count);
+ count = responder_only ? (u_int)ref_cur(&this->half_open_count_responder)
+ : (u_int)ref_cur(&this->half_open_count);
}
return count;
}
@@ -2055,8 +2092,10 @@ METHOD(ike_sa_manager_t, flush, void,
charon->bus->set_sa(charon->bus, NULL);
unlock_all_segments(this);
+ this->rng_lock->write_lock(this->rng_lock);
this->rng->destroy(this->rng);
this->rng = NULL;
+ this->rng_lock->unlock(this->rng_lock);
}
METHOD(ike_sa_manager_t, destroy, void,
@@ -2081,6 +2120,7 @@ METHOD(ike_sa_manager_t, destroy, void,
free(this->connected_peers_segments);
free(this->init_hashes_segments);
+ this->rng_lock->destroy(this->rng_lock);
free(this);
}
@@ -2138,6 +2178,7 @@ ike_sa_manager_t *ike_sa_manager_create()
free(this);
return NULL;
}
+ this->rng_lock = rwlock_create(RWLOCK_TYPE_DEFAULT);
this->ikesa_limit = lib->settings->get_int(lib->settings,
"%s.ikesa_limit", 0, lib->ns);
diff --git a/src/libcharon/sa/ike_sa_manager.h b/src/libcharon/sa/ike_sa_manager.h
index f259d8e56..3ea928ea5 100644
--- a/src/libcharon/sa/ike_sa_manager.h
+++ b/src/libcharon/sa/ike_sa_manager.h
@@ -216,14 +216,15 @@ struct ike_sa_manager_t {
* To prevent the server from resource exhaustion, cookies and other
* mechanisms are used. The number of half open IKE_SAs is a good
* indicator to see if a peer is flooding the server.
- * If a host is supplied, only the number of half open IKE_SAs initiated
- * from this IP are counted.
- * Only SAs for which we are the responder are counted.
+ * If a host is supplied, only the number of half open IKE_SAs with this IP
+ * are counted.
*
* @param ip NULL for all, IP for half open IKE_SAs with IP
+ * @param responder_only TRUE to return only the number of responding SAs
* @return number of half open IKE_SAs
*/
- u_int (*get_half_open_count) (ike_sa_manager_t *this, host_t *ip);
+ u_int (*get_half_open_count)(ike_sa_manager_t *this, host_t *ip,
+ bool responder_only);
/**
* Delete all existing IKE_SAs and destroy them immediately.
diff --git a/src/libcharon/sa/ikev1/phase1.c b/src/libcharon/sa/ikev1/phase1.c
index c968b2a9c..b7047e8fc 100644
--- a/src/libcharon/sa/ikev1/phase1.c
+++ b/src/libcharon/sa/ikev1/phase1.c
@@ -404,7 +404,7 @@ static auth_method_t get_pubkey_method(private_phase1_t *this, auth_cfg_t *auth)
id = (identification_t*)auth->get(auth, AUTH_RULE_IDENTITY);
if (id)
{
- private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, NULL);
+ private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, auth);
if (private)
{
switch (private->get_type(private))
diff --git a/src/libcharon/sa/ikev1/task_manager_v1.c b/src/libcharon/sa/ikev1/task_manager_v1.c
index ed547c4c2..678f99df1 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-2014 Tobias Brunner
+ * Copyright (C) 2007-2015 Tobias Brunner
* Copyright (C) 2007-2011 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -901,6 +901,34 @@ static bool process_dpd(private_task_manager_t *this, message_t *message)
}
/**
+ * Check if we already have a quick mode task queued for the exchange with the
+ * given message ID
+ */
+static bool have_quick_mode_task(private_task_manager_t *this, u_int32_t mid)
+{
+ enumerator_t *enumerator;
+ quick_mode_t *qm;
+ task_t *task;
+ bool found = FALSE;
+
+ enumerator = this->passive_tasks->create_enumerator(this->passive_tasks);
+ while (enumerator->enumerate(enumerator, &task))
+ {
+ if (task->get_type(task) == TASK_QUICK_MODE)
+ {
+ qm = (quick_mode_t*)task;
+ if (qm->get_mid(qm) == mid)
+ {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+ return found;
+}
+
+/**
* handle an incoming request message
*/
static status_t process_request(private_task_manager_t *this,
@@ -911,6 +939,7 @@ static status_t process_request(private_task_manager_t *this,
bool send_response = FALSE, dpd = FALSE;
if (message->get_exchange_type(message) == INFORMATIONAL_V1 ||
+ message->get_exchange_type(message) == QUICK_MODE ||
this->passive_tasks->get_count(this->passive_tasks) == 0)
{ /* create tasks depending on request type, if not already some queued */
switch (message->get_exchange_type(message))
@@ -946,6 +975,10 @@ static status_t process_request(private_task_manager_t *this,
"unestablished IKE_SA, ignored");
return FAILED;
}
+ if (have_quick_mode_task(this, message->get_message_id(message)))
+ {
+ break;
+ }
task = (task_t *)quick_mode_create(this->ike_sa, NULL,
NULL, NULL);
this->passive_tasks->insert_last(this->passive_tasks, task);
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.c b/src/libcharon/sa/ikev1/tasks/quick_mode.c
index 96edfd8d8..d6a3f2cd1 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.c
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Tobias Brunner
+ * Copyright (C) 2012-2015 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2011 Martin Willi
@@ -185,6 +185,11 @@ struct private_quick_mode_t {
*/
bool udp;
+ /**
+ * Message ID of handled quick mode exchange
+ */
+ u_int32_t mid;
+
/** states of quick mode */
enum {
QM_INIT,
@@ -1019,6 +1024,11 @@ static void check_for_rekeyed_child(private_quick_mode_t *this)
METHOD(task_t, process_r, status_t,
private_quick_mode_t *this, message_t *message)
{
+ if (this->mid && this->mid != message->get_message_id(message))
+ { /* not responsible for this quick mode exchange */
+ return NEED_MORE;
+ }
+
switch (this->state)
{
case QM_INIT:
@@ -1188,6 +1198,11 @@ METHOD(task_t, process_r, status_t,
METHOD(task_t, build_r, status_t,
private_quick_mode_t *this, message_t *message)
{
+ if (this->mid && this->mid != message->get_message_id(message))
+ { /* not responsible for this quick mode exchange */
+ return NEED_MORE;
+ }
+
switch (this->state)
{
case QM_INIT:
@@ -1242,6 +1257,7 @@ METHOD(task_t, build_r, status_t,
add_ts(this, message);
this->state = QM_NEGOTIATED;
+ this->mid = message->get_message_id(message);
return NEED_MORE;
}
case QM_NEGOTIATED:
@@ -1335,6 +1351,12 @@ METHOD(task_t, get_type, task_type_t,
return TASK_QUICK_MODE;
}
+METHOD(quick_mode_t, get_mid, u_int32_t,
+ private_quick_mode_t *this)
+{
+ return this->mid;
+}
+
METHOD(quick_mode_t, use_reqid, void,
private_quick_mode_t *this, u_int32_t reqid)
{
@@ -1368,6 +1390,7 @@ METHOD(task_t, migrate, void,
this->ike_sa = ike_sa;
this->keymat = (keymat_v1_t*)ike_sa->get_keymat(ike_sa);
this->state = QM_INIT;
+ this->mid = 0;
this->tsi = NULL;
this->tsr = NULL;
this->proposal = NULL;
@@ -1414,6 +1437,7 @@ quick_mode_t *quick_mode_create(ike_sa_t *ike_sa, child_cfg_t *config,
.migrate = _migrate,
.destroy = _destroy,
},
+ .get_mid = _get_mid,
.use_reqid = _use_reqid,
.use_marks = _use_marks,
.rekey = _rekey,
diff --git a/src/libcharon/sa/ikev1/tasks/quick_mode.h b/src/libcharon/sa/ikev1/tasks/quick_mode.h
index ee9b64d13..062d63465 100644
--- a/src/libcharon/sa/ikev1/tasks/quick_mode.h
+++ b/src/libcharon/sa/ikev1/tasks/quick_mode.h
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2011 Martin Willi
* Copyright (C) 2011 revosec AG
*
@@ -38,6 +41,14 @@ struct quick_mode_t {
task_t task;
/**
+ * Get the message ID of the quick mode exchange handled by this task as
+ * responder.
+ *
+ * @return message ID, or 0 (not defined yet or as initiator)
+ */
+ u_int32_t (*get_mid)(quick_mode_t *this);
+
+ /**
* Use a specific reqid to install this CHILD_SA.
*
* @param reqid reqid to use
diff --git a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
index f1442096c..91f6187f9 100644
--- a/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/eap_authenticator.c
@@ -448,6 +448,8 @@ static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
identification_t *other_id;
auth_cfg_t *auth;
keymat_v2_t *keymat;
+ eap_type_t type;
+ u_int32_t vendor;
auth_payload = (auth_payload_t*)message->get_payload(message,
PLV2_AUTH);
@@ -478,6 +480,13 @@ static bool verify_auth(private_eap_authenticator_t *this, message_t *message,
this->auth_complete = TRUE;
auth = this->ike_sa->get_auth_cfg(this->ike_sa, FALSE);
auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
+
+ type = this->method->get_type(this->method, &vendor);
+ auth->add(auth, AUTH_RULE_EAP_TYPE, type);
+ if (vendor)
+ {
+ auth->add(auth, AUTH_RULE_EAP_VENDOR, vendor);
+ }
return TRUE;
}
diff --git a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
index 151b49718..2284a484d 100644
--- a/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
+++ b/src/libcharon/sa/ikev2/authenticators/pubkey_authenticator.c
@@ -321,7 +321,7 @@ METHOD(authenticator_t, build, status_t,
chunk_t auth_data;
status_t status;
auth_payload_t *auth_payload;
- auth_method_t auth_method;
+ auth_method_t auth_method = AUTH_NONE;
id = this->ike_sa->get_my_id(this->ike_sa);
auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
diff --git a/src/libcharon/sa/ikev2/keymat_v2.c b/src/libcharon/sa/ikev2/keymat_v2.c
index 6fedc8eb5..fce0840e3 100644
--- a/src/libcharon/sa/ikev2/keymat_v2.c
+++ b/src/libcharon/sa/ikev2/keymat_v2.c
@@ -112,6 +112,7 @@ static bool derive_ike_aead(private_keymat_v2_t *this, u_int16_t alg,
case ENCR_AES_GCM_ICV12:
case ENCR_AES_GCM_ICV16:
/* RFC 4106 */
+ case ENCR_CHACHA20_POLY1305:
salt_size = 4;
break;
case ENCR_AES_CCM_ICV8:
@@ -527,6 +528,7 @@ METHOD(keymat_v2_t, derive_child_keys, bool,
case ENCR_AES_GCM_ICV16:
case ENCR_AES_CTR:
case ENCR_NULL_AUTH_AES_GMAC:
+ case ENCR_CHACHA20_POLY1305:
enc_size += 4;
break;
default:
diff --git a/src/libcharon/sa/ikev2/tasks/child_create.c b/src/libcharon/sa/ikev2/tasks/child_create.c
index e0f930c3c..e08f3dab1 100644
--- a/src/libcharon/sa/ikev2/tasks/child_create.c
+++ b/src/libcharon/sa/ikev2/tasks/child_create.c
@@ -145,6 +145,11 @@ struct private_child_create_t {
ipcomp_transform_t ipcomp_received;
/**
+ * IPsec protocol
+ */
+ protocol_id_t proto;
+
+ /**
* Own allocated SPI
*/
u_int32_t my_spi;
@@ -260,23 +265,23 @@ static bool allocate_spi(private_child_create_t *this)
{
enumerator_t *enumerator;
proposal_t *proposal;
- protocol_id_t proto = PROTO_ESP;
if (this->initiator)
{
+ this->proto = PROTO_ESP;
/* we just get a SPI for the first protocol. TODO: If we ever support
* proposal lists with mixed protocols, we'd need multiple SPIs */
if (this->proposals->get_first(this->proposals,
(void**)&proposal) == SUCCESS)
{
- proto = proposal->get_protocol(proposal);
+ this->proto = proposal->get_protocol(proposal);
}
}
else
{
- proto = this->proposal->get_protocol(this->proposal);
+ this->proto = this->proposal->get_protocol(this->proposal);
}
- this->my_spi = this->child_sa->alloc_spi(this->child_sa, proto);
+ this->my_spi = this->child_sa->alloc_spi(this->child_sa, this->proto);
if (this->my_spi)
{
if (this->initiator)
@@ -1352,20 +1357,16 @@ METHOD(task_t, build_i_delete, status_t,
private_child_create_t *this, message_t *message)
{
message->set_exchange_type(message, INFORMATIONAL);
- if (this->child_sa && this->proposal)
+ if (this->my_spi && this->proto)
{
- protocol_id_t proto;
delete_payload_t *del;
- u_int32_t spi;
- proto = this->proposal->get_protocol(this->proposal);
- spi = this->child_sa->get_spi(this->child_sa, TRUE);
- del = delete_payload_create(PLV2_DELETE, proto);
- del->add_spi(del, spi);
+ del = delete_payload_create(PLV2_DELETE, this->proto);
+ del->add_spi(del, this->my_spi);
message->add_payload(message, (payload_t*)del);
DBG1(DBG_IKE, "sending DELETE for %N CHILD_SA with SPI %.8x",
- protocol_id_names, proto, ntohl(spi));
+ protocol_id_names, this->proto, ntohl(this->my_spi));
}
return NEED_MORE;
}
@@ -1375,9 +1376,13 @@ METHOD(task_t, build_i_delete, status_t,
*/
static status_t delete_failed_sa(private_child_create_t *this)
{
- this->public.task.build = _build_i_delete;
- this->public.task.process = (void*)return_success;
- return NEED_MORE;
+ if (this->my_spi && this->proto)
+ {
+ this->public.task.build = _build_i_delete;
+ this->public.task.process = (void*)return_success;
+ return NEED_MORE;
+ }
+ return SUCCESS;
}
METHOD(task_t, process_i, status_t,
@@ -1596,6 +1601,7 @@ METHOD(task_t, migrate, void,
this->tsi = NULL;
this->tsr = NULL;
this->dh = NULL;
+ this->nonceg = NULL;
this->child_sa = NULL;
this->mode = MODE_TUNNEL;
this->ipcomp = IPCOMP_NONE;
diff --git a/src/libcharon/sa/ikev2/tasks/child_rekey.c b/src/libcharon/sa/ikev2/tasks/child_rekey.c
index c806e19ca..c7a8a1342 100644
--- a/src/libcharon/sa/ikev2/tasks/child_rekey.c
+++ b/src/libcharon/sa/ikev2/tasks/child_rekey.c
@@ -170,13 +170,8 @@ METHOD(task_t, build_i, status_t,
}
config = this->child_sa->get_config(this->child_sa);
- /* we just need the rekey notify ... */
- notify = notify_payload_create_from_protocol_and_type(PLV2_NOTIFY,
- this->protocol, REKEY_SA);
- notify->set_spi(notify, this->spi);
- message->add_payload(message, (payload_t*)notify);
- /* ... our CHILD_CREATE task does the hard work for us. */
+ /* our CHILD_CREATE task does the hard work for us */
if (!this->child_create)
{
this->child_create = child_create_create(this->ike_sa,
@@ -194,6 +189,14 @@ METHOD(task_t, build_i, status_t,
schedule_delayed_rekey(this);
return FAILED;
}
+ if (message->get_exchange_type(message) == CREATE_CHILD_SA)
+ {
+ /* don't add the notify if the CHILD_CREATE task changed the exchange */
+ notify = notify_payload_create_from_protocol_and_type(PLV2_NOTIFY,
+ this->protocol, REKEY_SA);
+ notify->set_spi(notify, this->spi);
+ message->add_payload(message, (payload_t*)notify);
+ }
this->child_sa->set_state(this->child_sa, CHILD_REKEYING);
return NEED_MORE;
@@ -334,8 +337,7 @@ METHOD(task_t, process_i, status_t,
if (this->child_create->task.process(&this->child_create->task,
message) == NEED_MORE)
{
- /* bad DH group while rekeying, try again */
- this->child_create->task.migrate(&this->child_create->task, this->ike_sa);
+ /* bad DH group while rekeying, retry, or failure requiring deletion */
return NEED_MORE;
}
if (message->get_payload(message, PLV2_SECURITY_ASSOCIATION) == NULL)
diff --git a/src/libcharon/sa/ikev2/tasks/ike_rekey.c b/src/libcharon/sa/ikev2/tasks/ike_rekey.c
index 1855517ce..eaba04e3a 100644
--- a/src/libcharon/sa/ikev2/tasks/ike_rekey.c
+++ b/src/libcharon/sa/ikev2/tasks/ike_rekey.c
@@ -116,7 +116,6 @@ static void establish_new(private_ike_rekey_t *this)
lib->processor->queue_job(lib->processor, job);
}
this->new_sa = NULL;
- /* set threads active IKE_SA after checkin */
charon->bus->set_sa(charon->bus, this->ike_sa);
}
}
@@ -229,9 +228,10 @@ METHOD(task_t, build_r, status_t,
if (this->ike_init->task.build(&this->ike_init->task, message) == FAILED)
{
+ charon->bus->set_sa(charon->bus, this->ike_sa);
return SUCCESS;
}
-
+ charon->bus->set_sa(charon->bus, this->ike_sa);
this->ike_sa->set_state(this->ike_sa, IKE_REKEYING);
/* rekeying successful, delete the IKE_SA using a subtask */
@@ -335,15 +335,13 @@ METHOD(task_t, process_i, status_t,
{
charon->ike_sa_manager->checkin(
charon->ike_sa_manager, this->new_sa);
- /* set threads active IKE_SA after checkin */
- charon->bus->set_sa(charon->bus, this->ike_sa);
}
+ charon->bus->set_sa(charon->bus, this->ike_sa);
this->new_sa = NULL;
establish_new(other);
return SUCCESS;
}
}
- /* set threads active IKE_SA after checkin */
charon->bus->set_sa(charon->bus, this->ike_sa);
}
@@ -372,9 +370,13 @@ METHOD(ike_rekey_t, collide, void,
this->collision = other;
}
-METHOD(task_t, migrate, void,
- private_ike_rekey_t *this, ike_sa_t *ike_sa)
+/**
+ * Cleanup the task
+ */
+static void cleanup(private_ike_rekey_t *this)
{
+ ike_sa_t *cur_sa;
+
if (this->ike_init)
{
this->ike_init->task.destroy(&this->ike_init->task);
@@ -383,9 +385,16 @@ METHOD(task_t, migrate, void,
{
this->ike_delete->task.destroy(&this->ike_delete->task);
}
+ cur_sa = charon->bus->get_sa(charon->bus);
DESTROY_IF(this->new_sa);
+ charon->bus->set_sa(charon->bus, cur_sa);
DESTROY_IF(this->collision);
+}
+METHOD(task_t, migrate, void,
+ private_ike_rekey_t *this, ike_sa_t *ike_sa)
+{
+ cleanup(this);
this->collision = NULL;
this->ike_sa = ike_sa;
this->new_sa = NULL;
@@ -396,16 +405,7 @@ METHOD(task_t, migrate, void,
METHOD(task_t, destroy, void,
private_ike_rekey_t *this)
{
- if (this->ike_init)
- {
- this->ike_init->task.destroy(&this->ike_init->task);
- }
- if (this->ike_delete)
- {
- this->ike_delete->task.destroy(&this->ike_delete->task);
- }
- DESTROY_IF(this->new_sa);
- DESTROY_IF(this->collision);
+ cleanup(this);
free(this);
}
diff --git a/src/libcharon/sa/shunt_manager.c b/src/libcharon/sa/shunt_manager.c
index 73e1abbf3..1a984435c 100644
--- a/src/libcharon/sa/shunt_manager.c
+++ b/src/libcharon/sa/shunt_manager.c
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
* Copyright (C) 2011 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
@@ -18,8 +19,10 @@
#include <hydra.h>
#include <daemon.h>
#include <threading/rwlock.h>
+#include <threading/rwlock_condvar.h>
#include <collections/linked_list.h>
+#define INSTALL_DISABLED ((u_int)~0)
typedef struct private_shunt_manager_t private_shunt_manager_t;
@@ -37,6 +40,21 @@ struct private_shunt_manager_t {
* Installed shunts, as child_cfg_t
*/
linked_list_t *shunts;
+
+ /**
+ * Lock to safely access the list of shunts
+ */
+ rwlock_t *lock;
+
+ /**
+ * Number of threads currently installing shunts, or INSTALL_DISABLED
+ */
+ u_int installing;
+
+ /**
+ * Condvar to signal shunt installation
+ */
+ rwlock_condvar_t *condvar;
};
/**
@@ -117,9 +135,15 @@ METHOD(shunt_manager_t, install, bool,
{
enumerator_t *enumerator;
child_cfg_t *child_cfg;
- bool found = FALSE;
+ bool found = FALSE, success;
/* check if not already installed */
+ this->lock->write_lock(this->lock);
+ if (this->installing == INSTALL_DISABLED)
+ { /* flush() has been called */
+ this->lock->unlock(this->lock);
+ return FALSE;
+ }
enumerator = this->shunts->create_enumerator(this->shunts);
while (enumerator->enumerate(enumerator, &child_cfg))
{
@@ -130,16 +154,29 @@ METHOD(shunt_manager_t, install, bool,
}
}
enumerator->destroy(enumerator);
-
if (found)
{
DBG1(DBG_CFG, "shunt %N policy '%s' already installed",
ipsec_mode_names, child->get_mode(child), child->get_name(child));
+ this->lock->unlock(this->lock);
return TRUE;
}
this->shunts->insert_last(this->shunts, child->get_ref(child));
+ this->installing++;
+ this->lock->unlock(this->lock);
- return install_shunt_policy(child);
+ success = install_shunt_policy(child);
+
+ this->lock->write_lock(this->lock);
+ if (!success)
+ {
+ this->shunts->remove(this->shunts, child, NULL);
+ child->destroy(child);
+ }
+ this->installing--;
+ this->condvar->signal(this->condvar);
+ this->lock->unlock(this->lock);
+ return success;
}
/**
@@ -215,6 +252,7 @@ METHOD(shunt_manager_t, uninstall, bool,
enumerator_t *enumerator;
child_cfg_t *child, *found = NULL;
+ this->lock->write_lock(this->lock);
enumerator = this->shunts->create_enumerator(this->shunts);
while (enumerator->enumerate(enumerator, &child))
{
@@ -226,6 +264,7 @@ METHOD(shunt_manager_t, uninstall, bool,
}
}
enumerator->destroy(enumerator);
+ this->lock->unlock(this->lock);
if (!found)
{
@@ -239,20 +278,37 @@ METHOD(shunt_manager_t, uninstall, bool,
METHOD(shunt_manager_t, create_enumerator, enumerator_t*,
private_shunt_manager_t *this)
{
- return this->shunts->create_enumerator(this->shunts);
+ this->lock->read_lock(this->lock);
+ return enumerator_create_cleaner(
+ this->shunts->create_enumerator(this->shunts),
+ (void*)this->lock->unlock, this->lock);
}
-METHOD(shunt_manager_t, destroy, void,
+METHOD(shunt_manager_t, flush, void,
private_shunt_manager_t *this)
{
child_cfg_t *child;
+ this->lock->write_lock(this->lock);
+ while (this->installing)
+ {
+ this->condvar->wait(this->condvar, this->lock);
+ }
while (this->shunts->remove_last(this->shunts, (void**)&child) == SUCCESS)
{
uninstall_shunt_policy(child);
child->destroy(child);
}
- this->shunts->destroy(this->shunts);
+ this->installing = INSTALL_DISABLED;
+ this->lock->unlock(this->lock);
+}
+
+METHOD(shunt_manager_t, destroy, void,
+ private_shunt_manager_t *this)
+{
+ this->shunts->destroy_offset(this->shunts, offsetof(child_cfg_t, destroy));
+ this->lock->destroy(this->lock);
+ this->condvar->destroy(this->condvar);
free(this);
}
@@ -268,9 +324,12 @@ shunt_manager_t *shunt_manager_create()
.install = _install,
.uninstall = _uninstall,
.create_enumerator = _create_enumerator,
+ .flush = _flush,
.destroy = _destroy,
},
.shunts = linked_list_create(),
+ .lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ .condvar = rwlock_condvar_create(),
);
return &this->public;
diff --git a/src/libcharon/sa/shunt_manager.h b/src/libcharon/sa/shunt_manager.h
index 28a795dc9..c43f5db3d 100644
--- a/src/libcharon/sa/shunt_manager.h
+++ b/src/libcharon/sa/shunt_manager.h
@@ -1,4 +1,5 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
* Copyright (C) 2011 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
@@ -56,6 +57,11 @@ struct shunt_manager_t {
enumerator_t* (*create_enumerator)(shunt_manager_t *this);
/**
+ * Clear any installed shunt.
+ */
+ void (*flush)(shunt_manager_t *this);
+
+ /**
* Destroy a shunt_manager_t.
*/
void (*destroy)(shunt_manager_t *this);
diff --git a/src/libcharon/sa/trap_manager.c b/src/libcharon/sa/trap_manager.c
index d6ff3c8c5..63505c960 100644
--- a/src/libcharon/sa/trap_manager.c
+++ b/src/libcharon/sa/trap_manager.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2013 Tobias Brunner
+ * Copyright (C) 2011-2015 Tobias Brunner
* Copyright (C) 2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -18,9 +18,12 @@
#include <hydra.h>
#include <daemon.h>
+#include <threading/mutex.h>
#include <threading/rwlock.h>
+#include <threading/rwlock_condvar.h>
#include <collections/linked_list.h>
+#define INSTALL_DISABLED ((u_int)~0)
typedef struct private_trap_manager_t private_trap_manager_t;
typedef struct trap_listener_t trap_listener_t;
@@ -67,6 +70,26 @@ struct private_trap_manager_t {
trap_listener_t listener;
/**
+ * list of acquires we currently handle
+ */
+ linked_list_t *acquires;
+
+ /**
+ * mutex for list of acquires
+ */
+ mutex_t *mutex;
+
+ /**
+ * number of threads currently installing trap policies, or INSTALL_DISABLED
+ */
+ u_int installing;
+
+ /**
+ * condvar to signal trap policy installation
+ */
+ rwlock_condvar_t *condvar;
+
+ /**
* Whether to ignore traffic selectors from acquires
*/
bool ignore_acquire_ts;
@@ -80,23 +103,58 @@ typedef struct {
char *name;
/** ref to peer_cfg to initiate */
peer_cfg_t *peer_cfg;
- /** ref to instanciated CHILD_SA */
+ /** ref to instantiated CHILD_SA (i.e the trap policy) */
child_sa_t *child_sa;
- /** TRUE if an acquire is pending */
- bool pending;
+ /** TRUE in case of wildcard Transport Mode SA */
+ bool wildcard;
+} entry_t;
+
+/**
+ * A handled acquire
+ */
+typedef struct {
/** pending IKE_SA connecting upon acquire */
ike_sa_t *ike_sa;
-} entry_t;
+ /** reqid of pending trap policy */
+ u_int32_t reqid;
+ /** destination address (wildcard case) */
+ host_t *dst;
+} acquire_t;
/**
* actually uninstall and destroy an installed entry
*/
-static void destroy_entry(entry_t *entry)
+static void destroy_entry(entry_t *this)
+{
+ this->child_sa->destroy(this->child_sa);
+ this->peer_cfg->destroy(this->peer_cfg);
+ free(this->name);
+ free(this);
+}
+
+/**
+ * destroy a cached acquire entry
+ */
+static void destroy_acquire(acquire_t *this)
{
- entry->child_sa->destroy(entry->child_sa);
- entry->peer_cfg->destroy(entry->peer_cfg);
- free(entry->name);
- free(entry);
+ DESTROY_IF(this->dst);
+ free(this);
+}
+
+/**
+ * match an acquire entry by reqid
+ */
+static bool acquire_by_reqid(acquire_t *this, u_int32_t *reqid)
+{
+ return this->reqid == *reqid;
+}
+
+/**
+ * match an acquire entry by destination address
+ */
+static bool acquire_by_dst(acquire_t *this, host_t *dst)
+{
+ return this->dst && this->dst->ip_equals(this->dst, dst);
}
METHOD(trap_manager_t, install, u_int32_t,
@@ -113,32 +171,49 @@ METHOD(trap_manager_t, install, u_int32_t,
linked_list_t *proposals;
proposal_t *proposal;
protocol_id_t proto = PROTO_ESP;
+ bool wildcard = FALSE;
/* try to resolve addresses */
ike_cfg = peer->get_ike_cfg(peer);
other = ike_cfg->resolve_other(ike_cfg, AF_UNSPEC);
- if (!other || other->is_anyaddr(other))
+ if (other && other->is_anyaddr(other) &&
+ child->get_mode(child) == MODE_TRANSPORT)
+ {
+ /* allow wildcard for Transport Mode SAs */
+ me = host_create_any(other->get_family(other));
+ wildcard = TRUE;
+ }
+ else if (!other || other->is_anyaddr(other))
{
DESTROY_IF(other);
DBG1(DBG_CFG, "installing trap failed, remote address unknown");
return 0;
}
- me = ike_cfg->resolve_me(ike_cfg, other->get_family(other));
- if (!me || me->is_anyaddr(me))
+ else
{
- DESTROY_IF(me);
- me = hydra->kernel_interface->get_source_addr(
- hydra->kernel_interface, other, NULL);
- if (!me)
+ me = ike_cfg->resolve_me(ike_cfg, other->get_family(other));
+ if (!me || me->is_anyaddr(me))
{
- DBG1(DBG_CFG, "installing trap failed, local address unknown");
- other->destroy(other);
- return 0;
+ DESTROY_IF(me);
+ me = hydra->kernel_interface->get_source_addr(
+ hydra->kernel_interface, other, NULL);
+ if (!me)
+ {
+ DBG1(DBG_CFG, "installing trap failed, local address unknown");
+ other->destroy(other);
+ return 0;
+ }
+ me->set_port(me, ike_cfg->get_my_port(ike_cfg));
}
- me->set_port(me, ike_cfg->get_my_port(ike_cfg));
}
this->lock->write_lock(this->lock);
+ if (this->installing == INSTALL_DISABLED)
+ { /* flush() has been called */
+ this->lock->unlock(this->lock);
+ me->destroy(me);
+ return 0;
+ }
enumerator = this->traps->create_enumerator(this->traps);
while (enumerator->enumerate(enumerator, &entry))
{
@@ -160,6 +235,7 @@ METHOD(trap_manager_t, install, u_int32_t,
{
DBG1(DBG_CFG, "CHILD_SA '%s' is already being routed", found->name);
this->lock->unlock(this->lock);
+ me->destroy(me);
return 0;
}
/* config might have changed so update everything */
@@ -170,8 +246,10 @@ METHOD(trap_manager_t, install, u_int32_t,
INIT(entry,
.name = strdup(child->get_name(child)),
.peer_cfg = peer->get_ref(peer),
+ .wildcard = wildcard,
);
this->traps->insert_first(this->traps, entry);
+ this->installing++;
/* don't hold lock while creating CHILD_SA and installing policies */
this->lock->unlock(this->lock);
@@ -220,6 +298,11 @@ METHOD(trap_manager_t, install, u_int32_t,
{
destroy_entry(found);
}
+ this->lock->write_lock(this->lock);
+ /* do this at the end, so entries created temporarily are also destroyed */
+ this->installing--;
+ this->condvar->signal(this->condvar);
+ this->lock->unlock(this->lock);
return reqid;
}
@@ -314,9 +397,12 @@ METHOD(trap_manager_t, acquire, void,
{
enumerator_t *enumerator;
entry_t *entry, *found = NULL;
+ acquire_t *acquire;
peer_cfg_t *peer;
child_cfg_t *child;
ike_sa_t *ike_sa;
+ host_t *host;
+ bool wildcard, ignore = FALSE;
this->lock->read_lock(this->lock);
enumerator = this->traps->create_enumerator(this->traps);
@@ -333,11 +419,52 @@ METHOD(trap_manager_t, acquire, void,
if (!found)
{
- DBG1(DBG_CFG, "trap not found, unable to acquire reqid %d",reqid);
+ DBG1(DBG_CFG, "trap not found, unable to acquire reqid %d", reqid);
this->lock->unlock(this->lock);
return;
}
- if (!cas_bool(&found->pending, FALSE, TRUE))
+ reqid = found->child_sa->get_reqid(found->child_sa);
+ wildcard = found->wildcard;
+
+ this->mutex->lock(this->mutex);
+ if (wildcard)
+ { /* for wildcard acquires we check that we don't have a pending acquire
+ * with the same peer */
+ u_int8_t mask;
+
+ dst->to_subnet(dst, &host, &mask);
+ if (this->acquires->find_first(this->acquires, (void*)acquire_by_dst,
+ (void**)&acquire, host) == SUCCESS)
+ {
+ host->destroy(host);
+ ignore = TRUE;
+ }
+ else
+ {
+ INIT(acquire,
+ .dst = host,
+ .reqid = reqid,
+ );
+ this->acquires->insert_last(this->acquires, acquire);
+ }
+ }
+ else
+ {
+ if (this->acquires->find_first(this->acquires, (void*)acquire_by_reqid,
+ (void**)&acquire, &reqid) == SUCCESS)
+ {
+ ignore = TRUE;
+ }
+ else
+ {
+ INIT(acquire,
+ .reqid = reqid,
+ );
+ this->acquires->insert_last(this->acquires, acquire);
+ }
+ }
+ this->mutex->unlock(this->mutex);
+ if (ignore)
{
DBG1(DBG_CFG, "ignoring acquire, connection attempt pending");
this->lock->unlock(this->lock);
@@ -346,12 +473,40 @@ METHOD(trap_manager_t, acquire, void,
peer = found->peer_cfg->get_ref(found->peer_cfg);
child = found->child_sa->get_config(found->child_sa);
child = child->get_ref(child);
- reqid = found->child_sa->get_reqid(found->child_sa);
/* don't hold the lock while checking out the IKE_SA */
this->lock->unlock(this->lock);
- ike_sa = charon->ike_sa_manager->checkout_by_config(
+ if (wildcard)
+ { /* the peer config would match IKE_SAs with other peers */
+ ike_sa = charon->ike_sa_manager->checkout_new(charon->ike_sa_manager,
+ peer->get_ike_version(peer), TRUE);
+ if (ike_sa)
+ {
+ ike_cfg_t *ike_cfg;
+ u_int16_t port;
+ u_int8_t mask;
+
+ ike_sa->set_peer_cfg(ike_sa, peer);
+ ike_cfg = ike_sa->get_ike_cfg(ike_sa);
+
+ port = ike_cfg->get_other_port(ike_cfg);
+ dst->to_subnet(dst, &host, &mask);
+ host->set_port(host, port);
+ ike_sa->set_other_host(ike_sa, host);
+
+ port = ike_cfg->get_my_port(ike_cfg);
+ src->to_subnet(src, &host, &mask);
+ host->set_port(host, port);
+ ike_sa->set_my_host(ike_sa, host);
+
+ charon->bus->set_sa(charon->bus, ike_sa);
+ }
+ }
+ else
+ {
+ ike_sa = charon->ike_sa_manager->checkout_by_config(
charon->ike_sa_manager, peer);
+ }
if (ike_sa)
{
if (ike_sa->get_peer_cfg(ike_sa) == NULL)
@@ -363,24 +518,29 @@ METHOD(trap_manager_t, acquire, void,
* have a single TS that we can establish in a Quick Mode. */
src = dst = NULL;
}
+
+ this->mutex->lock(this->mutex);
+ acquire->ike_sa = ike_sa;
+ this->mutex->unlock(this->mutex);
+
if (ike_sa->initiate(ike_sa, child, reqid, src, dst) != DESTROY_ME)
{
- /* make sure the entry is still there */
- this->lock->read_lock(this->lock);
- if (this->traps->find_first(this->traps, NULL,
- (void**)&found) == SUCCESS)
- {
- found->ike_sa = ike_sa;
- }
- this->lock->unlock(this->lock);
charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
}
else
{
- ike_sa->destroy(ike_sa);
- charon->bus->set_sa(charon->bus, NULL);
+ charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager,
+ ike_sa);
}
}
+ else
+ {
+ this->mutex->lock(this->mutex);
+ this->acquires->remove(this->acquires, acquire, NULL);
+ this->mutex->unlock(this->mutex);
+ destroy_acquire(acquire);
+ child->destroy(child);
+ }
peer->destroy(peer);
}
@@ -391,26 +551,33 @@ static void complete(private_trap_manager_t *this, ike_sa_t *ike_sa,
child_sa_t *child_sa)
{
enumerator_t *enumerator;
- entry_t *entry;
+ acquire_t *acquire;
- this->lock->read_lock(this->lock);
- enumerator = this->traps->create_enumerator(this->traps);
- while (enumerator->enumerate(enumerator, &entry))
+ this->mutex->lock(this->mutex);
+ enumerator = this->acquires->create_enumerator(this->acquires);
+ while (enumerator->enumerate(enumerator, &acquire))
{
- if (entry->ike_sa != ike_sa)
+ if (!acquire->ike_sa || acquire->ike_sa != ike_sa)
{
continue;
}
- if (child_sa && child_sa->get_reqid(child_sa) !=
- entry->child_sa->get_reqid(entry->child_sa))
+ if (child_sa)
{
- continue;
+ if (acquire->dst)
+ {
+ /* since every wildcard acquire results in a separate IKE_SA
+ * there is no need to compare the destination address */
+ }
+ else if (child_sa->get_reqid(child_sa) != acquire->reqid)
+ {
+ continue;
+ }
}
- entry->ike_sa = NULL;
- entry->pending = FALSE;
+ this->acquires->remove_at(this->acquires, enumerator);
+ destroy_acquire(acquire);
}
enumerator->destroy(enumerator);
- this->lock->unlock(this->lock);
+ this->mutex->unlock(this->mutex);
}
METHOD(listener_t, ike_state_change, bool,
@@ -444,14 +611,15 @@ METHOD(listener_t, child_state_change, bool,
METHOD(trap_manager_t, flush, void,
private_trap_manager_t *this)
{
- linked_list_t *traps;
- /* since destroying the CHILD_SA results in events which require a read
- * lock we cannot destroy the list while holding the write lock */
this->lock->write_lock(this->lock);
- traps = this->traps;
+ while (this->installing)
+ {
+ this->condvar->wait(this->condvar, this->lock);
+ }
+ this->traps->destroy_function(this->traps, (void*)destroy_entry);
this->traps = linked_list_create();
+ this->installing = INSTALL_DISABLED;
this->lock->unlock(this->lock);
- traps->destroy_function(traps, (void*)destroy_entry);
}
METHOD(trap_manager_t, destroy, void,
@@ -459,6 +627,9 @@ METHOD(trap_manager_t, destroy, void,
{
charon->bus->remove_listener(charon->bus, &this->listener.listener);
this->traps->destroy_function(this->traps, (void*)destroy_entry);
+ this->acquires->destroy_function(this->acquires, (void*)destroy_acquire);
+ this->condvar->destroy(this->condvar);
+ this->mutex->destroy(this->mutex);
this->lock->destroy(this->lock);
free(this);
}
@@ -488,7 +659,10 @@ trap_manager_t *trap_manager_create(void)
},
},
.traps = linked_list_create(),
+ .acquires = linked_list_create(),
+ .mutex = mutex_create(MUTEX_TYPE_DEFAULT),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
+ .condvar = rwlock_condvar_create(),
.ignore_acquire_ts = lib->settings->get_bool(lib->settings,
"%s.ignore_acquire_ts", FALSE, lib->ns),
);
diff --git a/src/libcharon/tests/Makefile.am b/src/libcharon/tests/Makefile.am
index c8be28594..5fd8ca26d 100644
--- a/src/libcharon/tests/Makefile.am
+++ b/src/libcharon/tests/Makefile.am
@@ -3,7 +3,9 @@ TESTS = libcharon_tests
check_PROGRAMS = $(TESTS)
libcharon_tests_SOURCES = \
+ suites/test_ike_cfg.c \
suites/test_mem_pool.c \
+ suites/test_message_chapoly.c \
libcharon_tests.h libcharon_tests.c
libcharon_tests_CFLAGS = \
@@ -11,6 +13,8 @@ libcharon_tests_CFLAGS = \
-I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libstrongswan/tests \
+ -DPLUGINDIR=\""$(abs_top_builddir)/src/libstrongswan/plugins\"" \
+ -DPLUGINS=\""${s_plugins}\"" \
@COVERAGE_CFLAGS@
libcharon_tests_LDFLAGS = @COVERAGE_LDFLAGS@
diff --git a/src/libcharon/tests/Makefile.in b/src/libcharon/tests/Makefile.in
index 7f4f4b24e..910aad928 100644
--- a/src/libcharon/tests/Makefile.in
+++ b/src/libcharon/tests/Makefile.in
@@ -102,7 +102,9 @@ CONFIG_CLEAN_VPATH_FILES =
am__EXEEXT_1 = libcharon_tests$(EXEEXT)
am__dirstamp = $(am__leading_dot)dirstamp
am_libcharon_tests_OBJECTS = \
+ suites/libcharon_tests-test_ike_cfg.$(OBJEXT) \
suites/libcharon_tests-test_mem_pool.$(OBJEXT) \
+ suites/libcharon_tests-test_message_chapoly.$(OBJEXT) \
libcharon_tests-libcharon_tests.$(OBJEXT)
libcharon_tests_OBJECTS = $(am_libcharon_tests_OBJECTS)
libcharon_tests_DEPENDENCIES = \
@@ -427,7 +429,9 @@ urandom_device = @urandom_device@
xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
libcharon_tests_SOURCES = \
+ suites/test_ike_cfg.c \
suites/test_mem_pool.c \
+ suites/test_message_chapoly.c \
libcharon_tests.h libcharon_tests.c
libcharon_tests_CFLAGS = \
@@ -435,6 +439,8 @@ libcharon_tests_CFLAGS = \
-I$(top_srcdir)/src/libhydra \
-I$(top_srcdir)/src/libstrongswan \
-I$(top_srcdir)/src/libstrongswan/tests \
+ -DPLUGINDIR=\""$(abs_top_builddir)/src/libstrongswan/plugins\"" \
+ -DPLUGINS=\""${s_plugins}\"" \
@COVERAGE_CFLAGS@
libcharon_tests_LDFLAGS = @COVERAGE_LDFLAGS@
@@ -493,8 +499,12 @@ suites/$(am__dirstamp):
suites/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) suites/$(DEPDIR)
@: > suites/$(DEPDIR)/$(am__dirstamp)
+suites/libcharon_tests-test_ike_cfg.$(OBJEXT): suites/$(am__dirstamp) \
+ suites/$(DEPDIR)/$(am__dirstamp)
suites/libcharon_tests-test_mem_pool.$(OBJEXT): \
suites/$(am__dirstamp) suites/$(DEPDIR)/$(am__dirstamp)
+suites/libcharon_tests-test_message_chapoly.$(OBJEXT): \
+ suites/$(am__dirstamp) suites/$(DEPDIR)/$(am__dirstamp)
libcharon_tests$(EXEEXT): $(libcharon_tests_OBJECTS) $(libcharon_tests_DEPENDENCIES) $(EXTRA_libcharon_tests_DEPENDENCIES)
@rm -f libcharon_tests$(EXEEXT)
@@ -508,7 +518,9 @@ distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libcharon_tests-libcharon_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/libcharon_tests-test_ike_cfg.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/libcharon_tests-test_mem_pool.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/libcharon_tests-test_message_chapoly.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
@@ -534,6 +546,20 @@ distclean-compile:
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+suites/libcharon_tests-test_ike_cfg.o: suites/test_ike_cfg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -MT suites/libcharon_tests-test_ike_cfg.o -MD -MP -MF suites/$(DEPDIR)/libcharon_tests-test_ike_cfg.Tpo -c -o suites/libcharon_tests-test_ike_cfg.o `test -f 'suites/test_ike_cfg.c' || echo '$(srcdir)/'`suites/test_ike_cfg.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/libcharon_tests-test_ike_cfg.Tpo suites/$(DEPDIR)/libcharon_tests-test_ike_cfg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_ike_cfg.c' object='suites/libcharon_tests-test_ike_cfg.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -c -o suites/libcharon_tests-test_ike_cfg.o `test -f 'suites/test_ike_cfg.c' || echo '$(srcdir)/'`suites/test_ike_cfg.c
+
+suites/libcharon_tests-test_ike_cfg.obj: suites/test_ike_cfg.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -MT suites/libcharon_tests-test_ike_cfg.obj -MD -MP -MF suites/$(DEPDIR)/libcharon_tests-test_ike_cfg.Tpo -c -o suites/libcharon_tests-test_ike_cfg.obj `if test -f 'suites/test_ike_cfg.c'; then $(CYGPATH_W) 'suites/test_ike_cfg.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_ike_cfg.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/libcharon_tests-test_ike_cfg.Tpo suites/$(DEPDIR)/libcharon_tests-test_ike_cfg.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_ike_cfg.c' object='suites/libcharon_tests-test_ike_cfg.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -c -o suites/libcharon_tests-test_ike_cfg.obj `if test -f 'suites/test_ike_cfg.c'; then $(CYGPATH_W) 'suites/test_ike_cfg.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_ike_cfg.c'; fi`
+
suites/libcharon_tests-test_mem_pool.o: suites/test_mem_pool.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -MT suites/libcharon_tests-test_mem_pool.o -MD -MP -MF suites/$(DEPDIR)/libcharon_tests-test_mem_pool.Tpo -c -o suites/libcharon_tests-test_mem_pool.o `test -f 'suites/test_mem_pool.c' || echo '$(srcdir)/'`suites/test_mem_pool.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/libcharon_tests-test_mem_pool.Tpo suites/$(DEPDIR)/libcharon_tests-test_mem_pool.Po
@@ -548,6 +574,20 @@ suites/libcharon_tests-test_mem_pool.obj: suites/test_mem_pool.c
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -c -o suites/libcharon_tests-test_mem_pool.obj `if test -f 'suites/test_mem_pool.c'; then $(CYGPATH_W) 'suites/test_mem_pool.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_mem_pool.c'; fi`
+suites/libcharon_tests-test_message_chapoly.o: suites/test_message_chapoly.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -MT suites/libcharon_tests-test_message_chapoly.o -MD -MP -MF suites/$(DEPDIR)/libcharon_tests-test_message_chapoly.Tpo -c -o suites/libcharon_tests-test_message_chapoly.o `test -f 'suites/test_message_chapoly.c' || echo '$(srcdir)/'`suites/test_message_chapoly.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/libcharon_tests-test_message_chapoly.Tpo suites/$(DEPDIR)/libcharon_tests-test_message_chapoly.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_message_chapoly.c' object='suites/libcharon_tests-test_message_chapoly.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -c -o suites/libcharon_tests-test_message_chapoly.o `test -f 'suites/test_message_chapoly.c' || echo '$(srcdir)/'`suites/test_message_chapoly.c
+
+suites/libcharon_tests-test_message_chapoly.obj: suites/test_message_chapoly.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -MT suites/libcharon_tests-test_message_chapoly.obj -MD -MP -MF suites/$(DEPDIR)/libcharon_tests-test_message_chapoly.Tpo -c -o suites/libcharon_tests-test_message_chapoly.obj `if test -f 'suites/test_message_chapoly.c'; then $(CYGPATH_W) 'suites/test_message_chapoly.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_message_chapoly.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/libcharon_tests-test_message_chapoly.Tpo suites/$(DEPDIR)/libcharon_tests-test_message_chapoly.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_message_chapoly.c' object='suites/libcharon_tests-test_message_chapoly.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -c -o suites/libcharon_tests-test_message_chapoly.obj `if test -f 'suites/test_message_chapoly.c'; then $(CYGPATH_W) 'suites/test_message_chapoly.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_message_chapoly.c'; fi`
+
libcharon_tests-libcharon_tests.o: libcharon_tests.c
@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libcharon_tests_CFLAGS) $(CFLAGS) -MT libcharon_tests-libcharon_tests.o -MD -MP -MF $(DEPDIR)/libcharon_tests-libcharon_tests.Tpo -c -o libcharon_tests-libcharon_tests.o `test -f 'libcharon_tests.c' || echo '$(srcdir)/'`libcharon_tests.c
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libcharon_tests-libcharon_tests.Tpo $(DEPDIR)/libcharon_tests-libcharon_tests.Po
diff --git a/src/libcharon/tests/libcharon_tests.c b/src/libcharon/tests/libcharon_tests.c
index 1ed0f0c95..ec96de711 100644
--- a/src/libcharon/tests/libcharon_tests.c
+++ b/src/libcharon/tests/libcharon_tests.c
@@ -27,8 +27,8 @@
static test_configuration_t tests[] = {
#define TEST_SUITE(x) \
{ .suite = x, },
-#define TEST_SUITE_DEPEND(x, type, args) \
- { .suite = x, .feature = PLUGIN_DEPENDS(type, args) },
+#define TEST_SUITE_DEPEND(x, type, ...) \
+ { .suite = x, .feature = PLUGIN_DEPENDS(type, __VA_ARGS__) },
#include "libcharon_tests.h"
{ .suite = NULL, }
};
@@ -37,13 +37,27 @@ static bool test_runner_init(bool init)
{
if (init)
{
+ char *plugins, *plugindir;
+
libhydra_init();
libcharon_init();
+
+ plugins = getenv("TESTS_PLUGINS") ?:
+ lib->settings->get_str(lib->settings,
+ "tests.load", PLUGINS);
+ plugindir = lib->settings->get_str(lib->settings,
+ "tests.plugindir", PLUGINDIR);
+ plugin_loader_add_plugindirs(plugindir, plugins);
+ if (!lib->plugins->load(lib->plugins, plugins))
+ {
+ return FALSE;
+ }
}
else
{
lib->processor->set_threads(lib->processor, 0);
lib->processor->cancel(lib->processor);
+ lib->plugins->unload(lib->plugins);
libcharon_deinit();
libhydra_deinit();
}
diff --git a/src/libcharon/tests/libcharon_tests.h b/src/libcharon/tests/libcharon_tests.h
index dc9681aeb..fb82baccb 100644
--- a/src/libcharon/tests/libcharon_tests.h
+++ b/src/libcharon/tests/libcharon_tests.h
@@ -13,4 +13,6 @@
* for more details.
*/
+TEST_SUITE(ike_cfg_suite_create)
TEST_SUITE(mem_pool_suite_create)
+TEST_SUITE_DEPEND(message_chapoly_suite_create, AEAD, ENCR_CHACHA20_POLY1305, 32)
diff --git a/src/libcharon/tests/suites/test_ike_cfg.c b/src/libcharon/tests/suites/test_ike_cfg.c
new file mode 100644
index 000000000..8062179b9
--- /dev/null
+++ b/src/libcharon/tests/suites/test_ike_cfg.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <config/ike_cfg.h>
+
+static void assert_family(int expected, char *addr, bool local)
+{
+ ike_cfg_t *cfg;
+ int family;
+
+ cfg = ike_cfg_create(IKEV2, FALSE, FALSE, local ? addr : "%any", 500,
+ local ? "%any" : addr, 500, FRAGMENTATION_NO, 0);
+ family = ike_cfg_get_family(cfg, local);
+ ck_assert_msg(expected == family, "expected family %d != %d (addr: '%s')",
+ expected, family, addr);
+ cfg->destroy(cfg);
+}
+
+START_TEST(test_get_address_family_empty)
+{
+ assert_family(AF_UNSPEC, "", _i);
+}
+END_TEST
+
+START_TEST(test_get_address_family_addr)
+{
+ assert_family(AF_INET, "192.168.1.1", _i);
+ assert_family(AF_INET6, "fec::1", _i);
+}
+END_TEST
+
+START_TEST(test_get_address_family_multi)
+{
+ assert_family(AF_INET, "192.168.1.1,192.168.2.2", _i);
+ assert_family(AF_INET6, "fec::1,fec::2", _i);
+
+ assert_family(AF_UNSPEC, "192.168.1.1,fec::1", _i);
+ assert_family(AF_UNSPEC, "fec::1,192.168.1.1", _i);
+}
+END_TEST
+
+START_TEST(test_get_address_family_any)
+{
+ assert_family(AF_UNSPEC, "%any", _i);
+
+ assert_family(AF_INET, "%any4", _i);
+ assert_family(AF_INET, "0.0.0.0", _i);
+
+ assert_family(AF_INET6, "%any6", _i);
+ assert_family(AF_INET6, "::", _i);
+
+ assert_family(AF_INET, "192.168.1.1,%any", _i);
+ assert_family(AF_INET, "192.168.1.1,%any4", _i);
+ assert_family(AF_UNSPEC, "192.168.1.1,%any6", _i);
+
+ assert_family(AF_INET6, "fec::1,%any", _i);
+ assert_family(AF_UNSPEC, "fec::1,%any4", _i);
+ assert_family(AF_INET6, "fec::1,%any6", _i);
+}
+END_TEST
+
+START_TEST(test_get_address_family_other)
+{
+ assert_family(AF_INET, "192.168.1.0", _i);
+ assert_family(AF_UNSPEC, "192.168.1.0/24", _i);
+ assert_family(AF_UNSPEC, "192.168.1.0-192.168.1.10", _i);
+
+ assert_family(AF_INET, "192.168.1.0/24,192.168.2.1", _i);
+ assert_family(AF_INET, "192.168.1.0-192.168.1.10,192.168.2.1", _i);
+ assert_family(AF_INET6, "192.168.1.0/24,fec::1", _i);
+ assert_family(AF_INET6, "192.168.1.0-192.168.1.10,fec::1", _i);
+
+ assert_family(AF_INET6, "fec::", _i);
+ assert_family(AF_UNSPEC, "fec::/64", _i);
+ assert_family(AF_UNSPEC, "fec::1-fec::10", _i);
+
+ assert_family(AF_INET6, "fec::/64,fed::1", _i);
+ assert_family(AF_INET6, "fec::1-fec::10,fec::1", _i);
+ assert_family(AF_INET, "fec::/64,192.168.1.1", _i);
+ assert_family(AF_INET, "fec::1-fec::10,192.168.1.1", _i);
+
+ assert_family(AF_UNSPEC, "strongswan.org", _i);
+ assert_family(AF_INET, "192.168.1.0,strongswan.org", _i);
+ assert_family(AF_INET6, "fec::1,strongswan.org", _i);
+}
+END_TEST
+
+Suite *ike_cfg_suite_create()
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("ike_cfg");
+
+ tc = tcase_create("ike_cfg_get_address_family");
+ tcase_add_loop_test(tc, test_get_address_family_empty, 0, 2);
+ tcase_add_loop_test(tc, test_get_address_family_addr, 0, 2);
+ tcase_add_loop_test(tc, test_get_address_family_multi, 0, 2);
+ tcase_add_loop_test(tc, test_get_address_family_any, 0, 2);
+ tcase_add_loop_test(tc, test_get_address_family_other, 0, 2);
+ suite_add_tcase(s, tc);
+
+ return s;
+}
diff --git a/src/libcharon/tests/suites/test_message_chapoly.c b/src/libcharon/tests/suites/test_message_chapoly.c
new file mode 100644
index 000000000..e871cf6c2
--- /dev/null
+++ b/src/libcharon/tests/suites/test_message_chapoly.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "test_suite.h"
+
+#include <encoding/message.h>
+
+static aead_t *aead;
+
+static iv_gen_t *ivgen;
+
+METHOD(keymat_t, get_version, ike_version_t,
+ keymat_t *this)
+{
+ return IKEV2;
+}
+
+METHOD(keymat_t, get_aead, aead_t*,
+ keymat_t *this, bool in)
+{
+ return aead;
+}
+
+METHOD(aead_t, get_iv_gen, iv_gen_t*,
+ aead_t *this)
+{
+ return ivgen;
+}
+
+METHOD(iv_gen_t, get_iv, bool,
+ iv_gen_t *this, u_int64_t seq, size_t size, u_int8_t *buffer)
+{
+ if (size != 8)
+ {
+ return FALSE;
+ }
+ memcpy(buffer, "\x10\x11\x12\x13\x14\x15\x16\x17", 8);
+ return TRUE;
+}
+
+METHOD(iv_gen_t, allocate_iv, bool,
+ iv_gen_t *this, u_int64_t seq, size_t size, chunk_t *chunk)
+{
+ if (size != 8)
+ {
+ return FALSE;
+ }
+ *chunk = chunk_alloc(size);
+ return get_iv(this, seq, chunk->len, chunk->ptr);
+}
+
+/**
+ * Appendix B draft-ietf-ipsecme-chacha20-poly1305-06
+ */
+START_TEST(test_chacha20poly1305)
+{
+ u_int64_t spii, spir;
+ ike_sa_id_t *id;
+ message_t *m;
+ u_int32_t window = htonl(10);
+ chunk_t chunk, exp;
+ keymat_t keymat = {
+ .get_version = _get_version,
+ .create_dh = (void*)return_null,
+ .create_nonce_gen = (void*)return_null,
+ .get_aead = _get_aead,
+ };
+
+ m = message_create(IKEV2, 0);
+ m->set_exchange_type(m, INFORMATIONAL);
+ htoun64(&spii, 0xc0c1c2c3c4c5c6c7);
+ htoun64(&spir, 0xd0d1d2d3d4d5d6d7);
+ id = ike_sa_id_create(IKEV2, spii, spir, FALSE);
+ m->set_ike_sa_id(m, id);
+ id->destroy(id);
+ m->set_source(m, host_create_from_string("1.2.3.4", 4500));
+ m->set_destination(m, host_create_from_string("4.3.2.1", 4500));
+ m->set_message_id(m, 9);
+ m->add_notify(m, TRUE, SET_WINDOW_SIZE, chunk_from_thing(window));
+
+ aead = lib->crypto->create_aead(lib->crypto, ENCR_CHACHA20_POLY1305, 32, 4);
+ ck_assert(aead);
+ ck_assert(aead->set_key(aead, chunk_from_chars(
+ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
+ 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
+ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
+ 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
+ 0xa0,0xa1,0xa2,0xa3)));
+ INIT(ivgen,
+ .get_iv = _get_iv,
+ .allocate_iv = _allocate_iv,
+ .destroy = (void*)free,
+ );
+ aead->get_iv_gen = _get_iv_gen,
+
+ ck_assert(m->generate(m, &keymat, NULL) == SUCCESS);
+ chunk = m->get_packet_data(m);
+ exp = chunk_from_chars(0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,
+ 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,
+ 0x2e,0x20,0x25,0x00,0x00,0x00,0x00,0x09,
+ 0x00,0x00,0x00,0x45,0x29,0x00,0x00,0x29,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x61,0x03,0x94,0x70,0x1f,0x8d,0x01,0x7f,
+ 0x7c,0x12,0x92,0x48,0x89,0x6b,0x71,0xbf,
+ 0xe2,0x52,0x36,0xef,0xd7,0xcd,0xc6,0x70,
+ 0x66,0x90,0x63,0x15,0xb2);
+ ck_assert_msg(chunk_equals(chunk, exp), "got %B\nexp %B", &chunk, &exp);
+ ivgen->destroy(ivgen);
+ aead->destroy(aead);
+ m->destroy(m);
+}
+END_TEST
+
+Suite *message_chapoly_suite_create()
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("chapoly");
+
+ tc = tcase_create("ChaCha20Poly1305 IKEv2 encryption");
+ tcase_add_test(tc, test_chacha20poly1305);
+ suite_add_tcase(s, tc);
+
+ return s;
+}
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
index f22e07d95..605476ef1 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_ipsec.c
@@ -199,6 +199,7 @@ static kernel_algorithm_t encryption_algs[] = {
/* {ENCR_CAMELLIA_CCM_ICV16, "***" }, */
{ENCR_SERPENT_CBC, "serpent" },
{ENCR_TWOFISH_CBC, "twofish" },
+ {ENCR_CHACHA20_POLY1305, "rfc7539esp(chacha20,poly1305)"},
};
/**
@@ -734,6 +735,7 @@ static struct xfrm_selector ts2selector(traffic_selector_t *src,
traffic_selector_t *dst)
{
struct xfrm_selector sel;
+ u_int16_t port;
memset(&sel, 0, sizeof(sel));
sel.family = (src->get_type(src) == TS_IPV4_ADDR_RANGE) ? AF_INET : AF_INET6;
@@ -746,13 +748,13 @@ static struct xfrm_selector ts2selector(traffic_selector_t *src,
if ((sel.proto == IPPROTO_ICMP || sel.proto == IPPROTO_ICMPV6) &&
(sel.dport || sel.sport))
{
- /* the ICMP type is encoded in the most significant 8 bits and the ICMP
- * code in the least significant 8 bits of the port. via XFRM we have
- * to pass the ICMP type and code in the source and destination port
- * fields, respectively. the port is in network byte order. */
- u_int16_t port = max(sel.dport, sel.sport);
- sel.sport = htons(port & 0xff);
- sel.dport = htons(port >> 8);
+ /* the kernel expects the ICMP type and code in the source and
+ * destination port fields, respectively. */
+ port = ntohs(max(sel.dport, sel.sport));
+ sel.sport = htons(traffic_selector_icmp_type(port));
+ sel.sport_mask = sel.sport ? ~0 : 0;
+ sel.dport = htons(traffic_selector_icmp_code(port));
+ sel.dport_mask = sel.dport ? ~0 : 0;
}
sel.ifindex = 0;
sel.user = 0;
@@ -1291,6 +1293,7 @@ METHOD(kernel_ipsec_t, add_sa, status_t,
case ENCR_AES_GCM_ICV16:
case ENCR_NULL_AUTH_AES_GMAC:
case ENCR_CAMELLIA_CCM_ICV16:
+ case ENCR_CHACHA20_POLY1305:
icv_size += 32;
/* FALL */
case ENCR_AES_CCM_ICV12:
@@ -2022,23 +2025,36 @@ METHOD(kernel_ipsec_t, flush_sas, status_t,
netlink_buf_t request;
struct nlmsghdr *hdr;
struct xfrm_usersa_flush *flush;
+ struct {
+ u_int8_t proto;
+ char *name;
+ } protos[] = {
+ { IPPROTO_AH, "AH" },
+ { IPPROTO_ESP, "ESP" },
+ { IPPROTO_COMP, "IPComp" },
+ };
+ int i;
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "flushing all SAD entries");
-
hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK;
hdr->nlmsg_type = XFRM_MSG_FLUSHSA;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct xfrm_usersa_flush));
flush = NLMSG_DATA(hdr);
- flush->proto = IPSEC_PROTO_ANY;
- if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+ for (i = 0; i < countof(protos); i++)
{
- DBG1(DBG_KNL, "unable to flush SAD entries");
- return FAILED;
+ DBG2(DBG_KNL, "flushing all %s SAD entries", protos[i].name);
+
+ flush->proto = protos[i].proto;
+
+ if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to flush %s SAD entries", protos[i].name);
+ return FAILED;
+ }
}
return SUCCESS;
}
@@ -2057,6 +2073,7 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
ipsec_sa_t *ipsec = mapping->sa;
struct xfrm_userpolicy_info *policy_info;
struct nlmsghdr *hdr;
+ status_t status;
int i;
/* clone the policy so we are able to check it out again later */
@@ -2151,7 +2168,14 @@ static status_t add_policy_internal(private_kernel_netlink_ipsec_t *this,
}
this->mutex->unlock(this->mutex);
- if (this->socket_xfrm->send_ack(this->socket_xfrm, hdr) != SUCCESS)
+ status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr);
+ if (status == ALREADY_DONE && !update)
+ {
+ DBG1(DBG_KNL, "policy already exists, try to update it");
+ hdr->nlmsg_type = XFRM_MSG_UPDPOLICY;
+ status = this->socket_xfrm->send_ack(this->socket_xfrm, hdr);
+ }
+ if (status != SUCCESS)
{
return FAILED;
}
@@ -2560,6 +2584,7 @@ METHOD(kernel_ipsec_t, del_policy, status_t,
if (!add_mark(hdr, sizeof(request), mark))
{
+ this->mutex->unlock(this->mutex);
return FAILED;
}
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
index 1515b01cc..4e5e02d07 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_net.c
@@ -491,6 +491,16 @@ struct private_kernel_netlink_net_t {
bool rta_prefsrc_for_ipv6;
/**
+ * whether marks can be used in route lookups
+ */
+ bool rta_mark;
+
+ /**
+ * the mark excluded from the routing rule used for virtual IPs
+ */
+ mark_t routing_mark;
+
+ /**
* whether to prefer temporary IPv6 addresses over public ones
*/
bool prefer_temporary_addrs;
@@ -1676,18 +1686,25 @@ static host_t *get_route(private_kernel_netlink_net_t *this, host_t *dest,
family = dest->get_family(dest);
hdr = &request.hdr;
hdr->nlmsg_flags = NLM_F_REQUEST;
- if (family == AF_INET || this->rta_prefsrc_for_ipv6 ||
- this->routing_table || match_net)
- { /* kernels prior to 3.0 do not support RTA_PREFSRC for IPv6 routes.
- * as we want to ignore routes with virtual IPs we cannot use DUMP
- * if these routes are not installed in a separate table */
- hdr->nlmsg_flags |= NLM_F_DUMP;
- }
hdr->nlmsg_type = RTM_GETROUTE;
hdr->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
msg = NLMSG_DATA(hdr);
msg->rtm_family = family;
+ if (!match_net && this->rta_mark && this->routing_mark.value)
+ {
+ /* if our routing rule excludes packets with a certain mark we can
+ * get the preferred route without having to dump all routes */
+ chunk = chunk_from_thing(this->routing_mark.value);
+ netlink_add_attribute(hdr, RTA_MARK, chunk, sizeof(request));
+ }
+ else if (family == AF_INET || this->rta_prefsrc_for_ipv6 ||
+ this->routing_table || match_net)
+ { /* kernels prior to 3.0 do not support RTA_PREFSRC for IPv6 routes.
+ * as we want to ignore routes with virtual IPs we cannot use DUMP
+ * if these routes are not installed in a separate table */
+ hdr->nlmsg_flags |= NLM_F_DUMP;
+ }
if (candidate)
{
chunk = candidate->get_address(candidate);
@@ -2412,6 +2429,10 @@ static status_t manage_rule(private_kernel_netlink_net_t *this, int nlmsg_type,
netlink_add_attribute(hdr, FRA_FWMARK, chunk, sizeof(request));
chunk = chunk_from_thing(mark.mask);
netlink_add_attribute(hdr, FRA_FWMASK, chunk, sizeof(request));
+ if (msg->rtm_flags & FIB_RULE_INVERT)
+ {
+ this->routing_mark = mark;
+ }
}
#else
DBG1(DBG_KNL, "setting firewall mark on routing rule is not supported");
@@ -2435,6 +2456,10 @@ static void check_kernel_features(private_kernel_netlink_net_t *this)
case 3:
if (a == 2)
{
+ if (b == 6 && c >= 36)
+ {
+ this->rta_mark = TRUE;
+ }
DBG2(DBG_KNL, "detected Linux %d.%d.%d, no support for "
"RTA_PREFSRC for IPv6 routes", a, b, c);
break;
@@ -2443,6 +2468,7 @@ static void check_kernel_features(private_kernel_netlink_net_t *this)
case 2:
/* only 3.x+ uses two part version numbers */
this->rta_prefsrc_for_ipv6 = TRUE;
+ this->rta_mark = TRUE;
break;
default:
break;
diff --git a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
index b0e3103d3..f7ce992a3 100644
--- a/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
+++ b/src/libhydra/plugins/kernel_netlink/kernel_netlink_shared.c
@@ -185,8 +185,8 @@ static ssize_t read_msg(private_netlink_socket_t *this,
return -1;
}
}
- len = recv(this->socket, buf, buflen, block ? 0 : MSG_DONTWAIT);
- if (len == buflen)
+ len = recv(this->socket, buf, buflen, MSG_TRUNC|(block ? 0 : MSG_DONTWAIT));
+ if (len > buflen)
{
DBG1(DBG_KNL, "netlink response exceeds buffer size");
return 0;
@@ -571,7 +571,7 @@ netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names,
.protocol = protocol,
.names = names,
.buflen = lib->settings->get_int(lib->settings,
- "%s.plugins.kernel-netlink.buflen", 4096, lib->ns),
+ "%s.plugins.kernel-netlink.buflen", 0, lib->ns),
.timeout = lib->settings->get_int(lib->settings,
"%s.plugins.kernel-netlink.timeout", 0, lib->ns),
.retries = lib->settings->get_int(lib->settings,
@@ -582,6 +582,16 @@ netlink_socket_t *netlink_socket_create(int protocol, enum_name_t *names,
.parallel = parallel,
);
+ if (!this->buflen)
+ {
+ long pagesize = sysconf(_SC_PAGESIZE);
+ if (pagesize == -1)
+ {
+ pagesize = 4096;
+ }
+ /* base this on NLMSG_GOODSIZE */
+ this->buflen = min(pagesize, 8192);
+ }
if (this->socket == -1)
{
DBG1(DBG_KNL, "unable to create netlink socket");
diff --git a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
index 3b32ba553..5027e1759 100644
--- a/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
+++ b/src/libhydra/plugins/kernel_pfkey/kernel_pfkey_ipsec.c
@@ -106,6 +106,12 @@
#define SADB_X_EALG_CASTCBC SADB_X_EALG_CAST128CBC
#endif
+#if !defined(SADB_X_EALG_AES_GCM_ICV8) && defined(SADB_X_EALG_AESGCM8)
+#define SADB_X_EALG_AES_GCM_ICV8 SADB_X_EALG_AESGCM8
+#define SADB_X_EALG_AES_GCM_ICV12 SADB_X_EALG_AESGCM12
+#define SADB_X_EALG_AES_GCM_ICV16 SADB_X_EALG_AESGCM16
+#endif
+
#ifndef SOL_IP
#define SOL_IP IPPROTO_IP
#define SOL_IPV6 IPPROTO_IPV6
@@ -508,15 +514,30 @@ static policy_entry_t *create_policy_entry(traffic_selector_t *src_ts,
INIT(policy,
.direction = dir,
);
+ u_int16_t port;
+ u_int8_t proto;
src_ts->to_subnet(src_ts, &policy->src.net, &policy->src.mask);
dst_ts->to_subnet(dst_ts, &policy->dst.net, &policy->dst.mask);
/* src or dest proto may be "any" (0), use more restrictive one */
- policy->src.proto = max(src_ts->get_protocol(src_ts),
- dst_ts->get_protocol(dst_ts));
- policy->src.proto = policy->src.proto ? policy->src.proto : IPSEC_PROTO_ANY;
- policy->dst.proto = policy->src.proto;
+ proto = max(src_ts->get_protocol(src_ts), dst_ts->get_protocol(dst_ts));
+ /* map the ports to ICMP type/code how the Linux kernel expects them, that
+ * is, type in src, code in dst */
+ if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)
+ {
+ port = max(policy->src.net->get_port(policy->src.net),
+ policy->dst.net->get_port(policy->dst.net));
+ policy->src.net->set_port(policy->src.net,
+ traffic_selector_icmp_type(port));
+ policy->dst.net->set_port(policy->dst.net,
+ traffic_selector_icmp_code(port));
+ }
+ else if (!proto)
+ {
+ proto = IPSEC_PROTO_ANY;
+ }
+ policy->src.proto = policy->dst.proto = proto;
return policy;
}
@@ -826,9 +847,11 @@ static kernel_algorithm_t encryption_algs[] = {
/* {ENCR_AES_CCM_ICV8, SADB_X_EALG_AES_CCM_ICV8 }, */
/* {ENCR_AES_CCM_ICV12, SADB_X_EALG_AES_CCM_ICV12 }, */
/* {ENCR_AES_CCM_ICV16, SADB_X_EALG_AES_CCM_ICV16 }, */
-/* {ENCR_AES_GCM_ICV8, SADB_X_EALG_AES_GCM_ICV8 }, */
-/* {ENCR_AES_GCM_ICV12, SADB_X_EALG_AES_GCM_ICV12 }, */
-/* {ENCR_AES_GCM_ICV16, SADB_X_EALG_AES_GCM_ICV16 }, */
+#ifdef SADB_X_EALG_AES_GCM_ICV8 /* assume the others are defined too */
+ {ENCR_AES_GCM_ICV8, SADB_X_EALG_AES_GCM_ICV8 },
+ {ENCR_AES_GCM_ICV12, SADB_X_EALG_AES_GCM_ICV12 },
+ {ENCR_AES_GCM_ICV16, SADB_X_EALG_AES_GCM_ICV16 },
+#endif
{END_OF_LIST, 0 },
};
@@ -942,28 +965,6 @@ static size_t hostcpy(void *dest, host_t *host, bool include_port)
}
/**
- * Copy a host_t as sockaddr_t to the given memory location and map the port to
- * ICMP/ICMPv6 message type/code as the Linux kernel expects it, that is, the
- * type in the source and the code in the destination address.
- * @return the number of bytes copied
- */
-static size_t hostcpy_icmp(void *dest, host_t *host, u_int16_t type)
-{
- size_t len;
-
- len = hostcpy(dest, host, TRUE);
- if (type == SADB_EXT_ADDRESS_SRC)
- {
- set_port(dest, traffic_selector_icmp_type(host->get_port(host)));
- }
- else
- {
- set_port(dest, traffic_selector_icmp_code(host->get_port(host)));
- }
- return len;
-}
-
-/**
* add a host to the given sadb_msg
*/
static void add_addr_ext(struct sadb_msg *msg, host_t *host, u_int16_t type,
@@ -975,14 +976,7 @@ static void add_addr_ext(struct sadb_msg *msg, host_t *host, u_int16_t type,
addr->sadb_address_exttype = type;
addr->sadb_address_proto = proto;
addr->sadb_address_prefixlen = prefixlen;
- if (proto == IPPROTO_ICMP || proto == IPPROTO_ICMPV6)
- {
- len = hostcpy_icmp(addr + 1, host, type);
- }
- else
- {
- len = hostcpy(addr + 1, host, include_port);
- }
+ len = hostcpy(addr + 1, host, include_port);
addr->sadb_address_len = PFKEY_LEN(sizeof(*addr) + len);
PFKEY_EXT_ADD(msg, addr);
}
@@ -2078,31 +2072,44 @@ METHOD(kernel_ipsec_t, flush_sas, status_t,
{
unsigned char request[PFKEY_BUFFER_SIZE];
struct sadb_msg *msg, *out;
+ struct {
+ u_int8_t proto;
+ char *name;
+ } protos[] = {
+ { SADB_SATYPE_AH, "AH" },
+ { SADB_SATYPE_ESP, "ESP" },
+ { SADB_X_SATYPE_IPCOMP, "IPComp" },
+ };
size_t len;
+ int i;
memset(&request, 0, sizeof(request));
- DBG2(DBG_KNL, "flushing all SAD entries");
-
msg = (struct sadb_msg*)request;
msg->sadb_msg_version = PF_KEY_V2;
msg->sadb_msg_type = SADB_FLUSH;
- msg->sadb_msg_satype = SADB_SATYPE_UNSPEC;
msg->sadb_msg_len = PFKEY_LEN(sizeof(struct sadb_msg));
- if (pfkey_send(this, msg, &out, &len) != SUCCESS)
- {
- DBG1(DBG_KNL, "unable to flush SAD entries");
- return FAILED;
- }
- else if (out->sadb_msg_errno)
+ for (i = 0; i < countof(protos); i++)
{
- DBG1(DBG_KNL, "unable to flush SAD entries: %s (%d)",
- strerror(out->sadb_msg_errno), out->sadb_msg_errno);
+ DBG2(DBG_KNL, "flushing all %s SAD entries", protos[i].name);
+
+ msg->sadb_msg_satype = protos[i].proto;
+ if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ {
+ DBG1(DBG_KNL, "unable to flush %s SAD entries", protos[i].name);
+ return FAILED;
+ }
+ else if (out->sadb_msg_errno)
+ {
+ DBG1(DBG_KNL, "unable to flush %s SAD entries: %s (%d)",
+ protos[i].name, strerror(out->sadb_msg_errno),
+ out->sadb_msg_errno);
+ free(out);
+ return FAILED;
+ }
free(out);
- return FAILED;
}
- free(out);
return SUCCESS;
}
@@ -2357,6 +2364,7 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
pfkey_msg_t response;
size_t len;
ipsec_mode_t proto_mode;
+ status_t status;
memset(&request, 0, sizeof(request));
@@ -2444,7 +2452,15 @@ static status_t add_policy_internal(private_kernel_pfkey_ipsec_t *this,
this->mutex->unlock(this->mutex);
- if (pfkey_send(this, msg, &out, &len) != SUCCESS)
+ status = pfkey_send(this, msg, &out, &len);
+ if (status == SUCCESS && !update && out->sadb_msg_errno == EEXIST)
+ {
+ DBG1(DBG_KNL, "policy already exists, try to update it");
+ free(out);
+ msg->sadb_msg_type = SADB_X_SPDUPDATE;
+ status = pfkey_send(this, msg, &out, &len);
+ }
+ if (status != SUCCESS)
{
return FAILED;
}
diff --git a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c
index 0f7802270..df80c29b8 100644
--- a/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c
+++ b/src/libhydra/plugins/kernel_pfroute/kernel_pfroute_net.c
@@ -408,6 +408,11 @@ struct private_kernel_pfroute_net_t
* Time in ms to wait for IP addresses to appear/disappear
*/
int vip_wait;
+
+ /**
+ * whether to actually install virtual IPs
+ */
+ bool install_virtual_ip;
};
@@ -1197,6 +1202,11 @@ METHOD(kernel_net_t, add_ip, status_t,
tun_device_t *tun;
bool timeout = FALSE;
+ if (!this->install_virtual_ip)
+ { /* disabled by config */
+ return SUCCESS;
+ }
+
tun = tun_device_create(NULL);
if (!tun)
{
@@ -1271,6 +1281,11 @@ METHOD(kernel_net_t, del_ip, status_t,
host_t *addr;
bool timeout = FALSE, found = FALSE;
+ if (!this->install_virtual_ip)
+ { /* disabled by config */
+ return SUCCESS;
+ }
+
this->lock->write_lock(this->lock);
enumerator = this->tuns->create_enumerator(this->tuns);
while (enumerator->enumerate(enumerator, &tun))
@@ -1848,6 +1863,8 @@ kernel_pfroute_net_t *kernel_pfroute_net_create()
.roam_lock = spinlock_create(),
.vip_wait = lib->settings->get_int(lib->settings,
"%s.plugins.kernel-pfroute.vip_wait", 1000, lib->ns),
+ .install_virtual_ip = lib->settings->get_bool(lib->settings,
+ "%s.install_virtual_ip", TRUE, lib->ns),
);
timerclear(&this->last_route_reinstall);
timerclear(&this->next_roam);
diff --git a/src/libhydra/tests/hydra_tests.c b/src/libhydra/tests/hydra_tests.c
index 90abd8369..0d6387be7 100644
--- a/src/libhydra/tests/hydra_tests.c
+++ b/src/libhydra/tests/hydra_tests.c
@@ -26,8 +26,8 @@
static test_configuration_t tests[] = {
#define TEST_SUITE(x) \
{ .suite = x, },
-#define TEST_SUITE_DEPEND(x, type, args) \
- { .suite = x, .feature = PLUGIN_DEPENDS(type, args) },
+#define TEST_SUITE_DEPEND(x, type, ...) \
+ { .suite = x, .feature = PLUGIN_DEPENDS(type, __VA_ARGS__) },
#include "hydra_tests.h"
{ .suite = NULL, }
};
diff --git a/src/libimcv/Android.mk b/src/libimcv/Android.mk
index 8269d7296..80e2aaadb 100644
--- a/src/libimcv/Android.mk
+++ b/src/libimcv/Android.mk
@@ -18,11 +18,13 @@ libimcv_la_SOURCES := \
imv/imv_session.h imv/imv_session.c \
imv/imv_session_manager.h imv/imv_session_manager.c \
imv/imv_workitem.h imv/imv_workitem.c \
+ generic/generic_attr_bool.h generic/generic_attr_bool.c \
+ generic/generic_attr_chunk.h generic/generic_attr_chunk.c \
+ generic/generic_attr_string.h generic/generic_attr_string.c \
ietf/ietf_attr.h ietf/ietf_attr.c \
ietf/ietf_attr_assess_result.h ietf/ietf_attr_assess_result.c \
ietf/ietf_attr_attr_request.h ietf/ietf_attr_attr_request.c \
ietf/ietf_attr_fwd_enabled.h ietf/ietf_attr_fwd_enabled.c \
- ietf/ietf_attr_default_pwd_enabled.h ietf/ietf_attr_default_pwd_enabled.c \
ietf/ietf_attr_installed_packages.h ietf/ietf_attr_installed_packages.c \
ietf/ietf_attr_numeric_version.h ietf/ietf_attr_numeric_version.c \
ietf/ietf_attr_op_status.h ietf/ietf_attr_op_status.c \
@@ -37,7 +39,6 @@ libimcv_la_SOURCES := \
ita/ita_attr_get_settings.h ita/ita_attr_get_settings.c \
ita/ita_attr_settings.h ita/ita_attr_settings.c \
ita/ita_attr_angel.h ita/ita_attr_angel.c \
- ita/ita_attr_device_id.h ita/ita_attr_device_id.c \
os_info/os_info.h os_info/os_info.c \
pa_tnc/pa_tnc_attr.h \
pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
@@ -66,6 +67,8 @@ libimcv_la_SOURCES := \
pts/components/ita/ita_comp_tboot.h pts/components/ita/ita_comp_tboot.c \
pts/components/ita/ita_comp_tgrub.h pts/components/ita/ita_comp_tgrub.c \
pts/components/tcg/tcg_comp_func_name.h pts/components/tcg/tcg_comp_func_name.c \
+ pwg/pwg_attr.h pwg/pwg_attr.c \
+ pwg/pwg_attr_vendor_smi_code.h pwg/pwg_attr_vendor_smi_code.c \
seg/seg_contract.h seg/seg_contract.c \
seg/seg_contract_manager.h seg/seg_contract_manager.c \
seg/seg_env.h seg/seg_env.c \
diff --git a/src/libimcv/Makefile.am b/src/libimcv/Makefile.am
index a61382723..7683da3af 100644
--- a/src/libimcv/Makefile.am
+++ b/src/libimcv/Makefile.am
@@ -36,11 +36,13 @@ libimcv_la_SOURCES = \
imv/imv_session.h imv/imv_session.c \
imv/imv_session_manager.h imv/imv_session_manager.c \
imv/imv_workitem.h imv/imv_workitem.c \
+ generic/generic_attr_bool.h generic/generic_attr_bool.c \
+ generic/generic_attr_chunk.h generic/generic_attr_chunk.c \
+ generic/generic_attr_string.h generic/generic_attr_string.c \
ietf/ietf_attr.h ietf/ietf_attr.c \
ietf/ietf_attr_assess_result.h ietf/ietf_attr_assess_result.c \
ietf/ietf_attr_attr_request.h ietf/ietf_attr_attr_request.c \
ietf/ietf_attr_fwd_enabled.h ietf/ietf_attr_fwd_enabled.c \
- ietf/ietf_attr_default_pwd_enabled.h ietf/ietf_attr_default_pwd_enabled.c \
ietf/ietf_attr_installed_packages.h ietf/ietf_attr_installed_packages.c \
ietf/ietf_attr_numeric_version.h ietf/ietf_attr_numeric_version.c \
ietf/ietf_attr_op_status.h ietf/ietf_attr_op_status.c \
@@ -55,7 +57,6 @@ libimcv_la_SOURCES = \
ita/ita_attr_get_settings.h ita/ita_attr_get_settings.c \
ita/ita_attr_settings.h ita/ita_attr_settings.c \
ita/ita_attr_angel.h ita/ita_attr_angel.c \
- ita/ita_attr_device_id.h ita/ita_attr_device_id.c \
os_info/os_info.h os_info/os_info.c \
pa_tnc/pa_tnc_attr.h \
pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
@@ -84,6 +85,8 @@ libimcv_la_SOURCES = \
pts/components/ita/ita_comp_tboot.h pts/components/ita/ita_comp_tboot.c \
pts/components/ita/ita_comp_tgrub.h pts/components/ita/ita_comp_tgrub.c \
pts/components/tcg/tcg_comp_func_name.h pts/components/tcg/tcg_comp_func_name.c \
+ pwg/pwg_attr.h pwg/pwg_attr.c \
+ pwg/pwg_attr_vendor_smi_code.h pwg/pwg_attr_vendor_smi_code.c \
seg/seg_contract.h seg/seg_contract.c \
seg/seg_contract_manager.h seg/seg_contract_manager.c \
seg/seg_env.h seg/seg_env.c \
@@ -173,6 +176,14 @@ if USE_IMV_SWID
SUBDIRS += plugins/imv_swid
endif
+if USE_IMC_HCD
+ SUBDIRS += plugins/imc_hcd
+endif
+
+if USE_IMV_HCD
+ SUBDIRS += plugins/imv_hcd
+endif
+
TESTS = imcv_tests
check_PROGRAMS = $(TESTS)
diff --git a/src/libimcv/Makefile.in b/src/libimcv/Makefile.in
index 03778a22c..ed2934cfb 100644
--- a/src/libimcv/Makefile.in
+++ b/src/libimcv/Makefile.in
@@ -94,6 +94,8 @@ ipsec_PROGRAMS = imv_policy_manager$(EXEEXT)
@USE_IMV_ATTESTATION_TRUE@am__append_10 = plugins/imv_attestation
@USE_IMC_SWID_TRUE@am__append_11 = plugins/imc_swid
@USE_IMV_SWID_TRUE@am__append_12 = plugins/imv_swid
+@USE_IMC_HCD_TRUE@am__append_13 = plugins/imc_hcd
+@USE_IMV_HCD_TRUE@am__append_14 = plugins/imv_hcd
TESTS = imcv_tests$(EXEEXT)
check_PROGRAMS = $(am__EXEEXT_1)
subdir = src/libimcv
@@ -157,10 +159,10 @@ am_libimcv_la_OBJECTS = imcv.lo imc/imc_agent.lo imc/imc_msg.lo \
imv/imv_msg.lo imv/imv_lang_string.lo imv/imv_os_info.lo \
imv/imv_reason_string.lo imv/imv_remediation_string.lo \
imv/imv_session.lo imv/imv_session_manager.lo \
- imv/imv_workitem.lo ietf/ietf_attr.lo \
- ietf/ietf_attr_assess_result.lo ietf/ietf_attr_attr_request.lo \
- ietf/ietf_attr_fwd_enabled.lo \
- ietf/ietf_attr_default_pwd_enabled.lo \
+ imv/imv_workitem.lo generic/generic_attr_bool.lo \
+ generic/generic_attr_chunk.lo generic/generic_attr_string.lo \
+ ietf/ietf_attr.lo ietf/ietf_attr_assess_result.lo \
+ ietf/ietf_attr_attr_request.lo ietf/ietf_attr_fwd_enabled.lo \
ietf/ietf_attr_installed_packages.lo \
ietf/ietf_attr_numeric_version.lo ietf/ietf_attr_op_status.lo \
ietf/ietf_attr_pa_tnc_error.lo ietf/ietf_attr_port_filter.lo \
@@ -169,8 +171,7 @@ am_libimcv_la_OBJECTS = imcv.lo imc/imc_agent.lo imc/imc_msg.lo \
ietf/ietf_attr_string_version.lo ita/ita_attr.lo \
ita/ita_attr_command.lo ita/ita_attr_dummy.lo \
ita/ita_attr_get_settings.lo ita/ita_attr_settings.lo \
- ita/ita_attr_angel.lo ita/ita_attr_device_id.lo \
- os_info/os_info.lo pa_tnc/pa_tnc_msg.lo \
+ ita/ita_attr_angel.lo os_info/os_info.lo pa_tnc/pa_tnc_msg.lo \
pa_tnc/pa_tnc_attr_manager.lo pts/pts.lo pts/pts_error.lo \
pts/pts_pcr.lo pts/pts_creds.lo pts/pts_database.lo \
pts/pts_dh_group.lo pts/pts_file_meas.lo pts/pts_file_meta.lo \
@@ -183,7 +184,8 @@ am_libimcv_la_OBJECTS = imcv.lo imc/imc_agent.lo imc/imc_msg.lo \
pts/components/ita/ita_comp_ima.lo \
pts/components/ita/ita_comp_tboot.lo \
pts/components/ita/ita_comp_tgrub.lo \
- pts/components/tcg/tcg_comp_func_name.lo seg/seg_contract.lo \
+ pts/components/tcg/tcg_comp_func_name.lo pwg/pwg_attr.lo \
+ pwg/pwg_attr_vendor_smi_code.lo seg/seg_contract.lo \
seg/seg_contract_manager.lo seg/seg_env.lo swid/swid_error.lo \
swid/swid_inventory.lo swid/swid_tag.lo swid/swid_tag_id.lo \
tcg/tcg_attr.lo tcg/pts/tcg_pts_attr_proto_caps.lo \
@@ -344,7 +346,8 @@ am__tty_colors = { \
DIST_SUBDIRS = . plugins/imc_test plugins/imv_test plugins/imc_scanner \
plugins/imv_scanner plugins/imc_os plugins/imv_os \
plugins/imc_attestation plugins/imv_attestation \
- plugins/imc_swid plugins/imv_swid
+ plugins/imc_swid plugins/imv_swid plugins/imc_hcd \
+ plugins/imv_hcd
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -625,11 +628,13 @@ libimcv_la_SOURCES = \
imv/imv_session.h imv/imv_session.c \
imv/imv_session_manager.h imv/imv_session_manager.c \
imv/imv_workitem.h imv/imv_workitem.c \
+ generic/generic_attr_bool.h generic/generic_attr_bool.c \
+ generic/generic_attr_chunk.h generic/generic_attr_chunk.c \
+ generic/generic_attr_string.h generic/generic_attr_string.c \
ietf/ietf_attr.h ietf/ietf_attr.c \
ietf/ietf_attr_assess_result.h ietf/ietf_attr_assess_result.c \
ietf/ietf_attr_attr_request.h ietf/ietf_attr_attr_request.c \
ietf/ietf_attr_fwd_enabled.h ietf/ietf_attr_fwd_enabled.c \
- ietf/ietf_attr_default_pwd_enabled.h ietf/ietf_attr_default_pwd_enabled.c \
ietf/ietf_attr_installed_packages.h ietf/ietf_attr_installed_packages.c \
ietf/ietf_attr_numeric_version.h ietf/ietf_attr_numeric_version.c \
ietf/ietf_attr_op_status.h ietf/ietf_attr_op_status.c \
@@ -644,7 +649,6 @@ libimcv_la_SOURCES = \
ita/ita_attr_get_settings.h ita/ita_attr_get_settings.c \
ita/ita_attr_settings.h ita/ita_attr_settings.c \
ita/ita_attr_angel.h ita/ita_attr_angel.c \
- ita/ita_attr_device_id.h ita/ita_attr_device_id.c \
os_info/os_info.h os_info/os_info.c \
pa_tnc/pa_tnc_attr.h \
pa_tnc/pa_tnc_msg.h pa_tnc/pa_tnc_msg.c \
@@ -673,6 +677,8 @@ libimcv_la_SOURCES = \
pts/components/ita/ita_comp_tboot.h pts/components/ita/ita_comp_tboot.c \
pts/components/ita/ita_comp_tgrub.h pts/components/ita/ita_comp_tgrub.c \
pts/components/tcg/tcg_comp_func_name.h pts/components/tcg/tcg_comp_func_name.c \
+ pwg/pwg_attr.h pwg/pwg_attr.c \
+ pwg/pwg_attr_vendor_smi_code.h pwg/pwg_attr_vendor_smi_code.c \
seg/seg_contract.h seg/seg_contract.c \
seg/seg_contract_manager.h seg/seg_contract_manager.c \
seg/seg_env.h seg/seg_env.c \
@@ -721,7 +727,7 @@ imv_policy_manager_LDADD = \
SUBDIRS = . $(am__append_3) $(am__append_4) $(am__append_5) \
$(am__append_6) $(am__append_7) $(am__append_8) \
$(am__append_9) $(am__append_10) $(am__append_11) \
- $(am__append_12)
+ $(am__append_12) $(am__append_13) $(am__append_14)
imcv_tests_SOURCES = \
ita/ita_attr_command.c \
pa_tnc/pa_tnc_attr_manager.c \
@@ -842,6 +848,18 @@ imv/imv_session.lo: imv/$(am__dirstamp) imv/$(DEPDIR)/$(am__dirstamp)
imv/imv_session_manager.lo: imv/$(am__dirstamp) \
imv/$(DEPDIR)/$(am__dirstamp)
imv/imv_workitem.lo: imv/$(am__dirstamp) imv/$(DEPDIR)/$(am__dirstamp)
+generic/$(am__dirstamp):
+ @$(MKDIR_P) generic
+ @: > generic/$(am__dirstamp)
+generic/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) generic/$(DEPDIR)
+ @: > generic/$(DEPDIR)/$(am__dirstamp)
+generic/generic_attr_bool.lo: generic/$(am__dirstamp) \
+ generic/$(DEPDIR)/$(am__dirstamp)
+generic/generic_attr_chunk.lo: generic/$(am__dirstamp) \
+ generic/$(DEPDIR)/$(am__dirstamp)
+generic/generic_attr_string.lo: generic/$(am__dirstamp) \
+ generic/$(DEPDIR)/$(am__dirstamp)
ietf/$(am__dirstamp):
@$(MKDIR_P) ietf
@: > ietf/$(am__dirstamp)
@@ -855,8 +873,6 @@ ietf/ietf_attr_attr_request.lo: ietf/$(am__dirstamp) \
ietf/$(DEPDIR)/$(am__dirstamp)
ietf/ietf_attr_fwd_enabled.lo: ietf/$(am__dirstamp) \
ietf/$(DEPDIR)/$(am__dirstamp)
-ietf/ietf_attr_default_pwd_enabled.lo: ietf/$(am__dirstamp) \
- ietf/$(DEPDIR)/$(am__dirstamp)
ietf/ietf_attr_installed_packages.lo: ietf/$(am__dirstamp) \
ietf/$(DEPDIR)/$(am__dirstamp)
ietf/ietf_attr_numeric_version.lo: ietf/$(am__dirstamp) \
@@ -890,8 +906,6 @@ ita/ita_attr_settings.lo: ita/$(am__dirstamp) \
ita/$(DEPDIR)/$(am__dirstamp)
ita/ita_attr_angel.lo: ita/$(am__dirstamp) \
ita/$(DEPDIR)/$(am__dirstamp)
-ita/ita_attr_device_id.lo: ita/$(am__dirstamp) \
- ita/$(DEPDIR)/$(am__dirstamp)
os_info/$(am__dirstamp):
@$(MKDIR_P) os_info
@: > os_info/$(am__dirstamp)
@@ -974,6 +988,15 @@ pts/components/tcg/$(DEPDIR)/$(am__dirstamp):
pts/components/tcg/tcg_comp_func_name.lo: \
pts/components/tcg/$(am__dirstamp) \
pts/components/tcg/$(DEPDIR)/$(am__dirstamp)
+pwg/$(am__dirstamp):
+ @$(MKDIR_P) pwg
+ @: > pwg/$(am__dirstamp)
+pwg/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) pwg/$(DEPDIR)
+ @: > pwg/$(DEPDIR)/$(am__dirstamp)
+pwg/pwg_attr.lo: pwg/$(am__dirstamp) pwg/$(DEPDIR)/$(am__dirstamp)
+pwg/pwg_attr_vendor_smi_code.lo: pwg/$(am__dirstamp) \
+ pwg/$(DEPDIR)/$(am__dirstamp)
seg/$(am__dirstamp):
@$(MKDIR_P) seg
@: > seg/$(am__dirstamp)
@@ -1201,6 +1224,8 @@ uninstall-ipsecSCRIPTS:
mostlyclean-compile:
-rm -f *.$(OBJEXT)
+ -rm -f generic/*.$(OBJEXT)
+ -rm -f generic/*.lo
-rm -f ietf/*.$(OBJEXT)
-rm -f ietf/*.lo
-rm -f imc/*.$(OBJEXT)
@@ -1221,6 +1246,8 @@ mostlyclean-compile:
-rm -f pts/components/ita/*.lo
-rm -f pts/components/tcg/*.$(OBJEXT)
-rm -f pts/components/tcg/*.lo
+ -rm -f pwg/*.$(OBJEXT)
+ -rm -f pwg/*.lo
-rm -f seg/*.$(OBJEXT)
-rm -f seg/*.lo
-rm -f suites/*.$(OBJEXT)
@@ -1241,10 +1268,12 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imcv.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imcv_tests-imcv.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imcv_tests-imcv_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@generic/$(DEPDIR)/generic_attr_bool.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@generic/$(DEPDIR)/generic_attr_chunk.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@generic/$(DEPDIR)/generic_attr_string.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/ietf_attr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/ietf_attr_assess_result.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/ietf_attr_attr_request.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/ietf_attr_default_pwd_enabled.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/ietf_attr_fwd_enabled.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/ietf_attr_installed_packages.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ietf/$(DEPDIR)/ietf_attr_numeric_version.Plo@am__quote@
@@ -1274,7 +1303,6 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@ita/$(DEPDIR)/ita_attr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ita/$(DEPDIR)/ita_attr_angel.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ita/$(DEPDIR)/ita_attr_command.Plo@am__quote@
-@AMDEP_TRUE@@am__include@ @am__quote@ita/$(DEPDIR)/ita_attr_device_id.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ita/$(DEPDIR)/ita_attr_dummy.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ita/$(DEPDIR)/ita_attr_get_settings.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@ita/$(DEPDIR)/ita_attr_settings.Plo@am__quote@
@@ -1302,6 +1330,8 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@pts/components/ita/$(DEPDIR)/ita_comp_tboot.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@pts/components/ita/$(DEPDIR)/ita_comp_tgrub.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@pts/components/tcg/$(DEPDIR)/tcg_comp_func_name.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pwg/$(DEPDIR)/pwg_attr.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@pwg/$(DEPDIR)/pwg_attr_vendor_smi_code.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@seg/$(DEPDIR)/imcv_tests-seg_contract.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@seg/$(DEPDIR)/imcv_tests-seg_contract_manager.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@seg/$(DEPDIR)/imcv_tests-seg_env.Po@am__quote@
@@ -1508,6 +1538,7 @@ mostlyclean-libtool:
clean-libtool:
-rm -rf .libs _libs
+ -rm -rf generic/.libs generic/_libs
-rm -rf ietf/.libs ietf/_libs
-rm -rf imc/.libs imc/_libs
-rm -rf imv/.libs imv/_libs
@@ -1518,6 +1549,7 @@ clean-libtool:
-rm -rf pts/components/.libs pts/components/_libs
-rm -rf pts/components/ita/.libs pts/components/ita/_libs
-rm -rf pts/components/tcg/.libs pts/components/tcg/_libs
+ -rm -rf pwg/.libs pwg/_libs
-rm -rf seg/.libs seg/_libs
-rm -rf swid/.libs swid/_libs
-rm -rf tcg/.libs tcg/_libs
@@ -1829,6 +1861,8 @@ clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f generic/$(DEPDIR)/$(am__dirstamp)
+ -rm -f generic/$(am__dirstamp)
-rm -f ietf/$(DEPDIR)/$(am__dirstamp)
-rm -f ietf/$(am__dirstamp)
-rm -f imc/$(DEPDIR)/$(am__dirstamp)
@@ -1849,6 +1883,8 @@ distclean-generic:
-rm -f pts/components/ita/$(am__dirstamp)
-rm -f pts/components/tcg/$(DEPDIR)/$(am__dirstamp)
-rm -f pts/components/tcg/$(am__dirstamp)
+ -rm -f pwg/$(DEPDIR)/$(am__dirstamp)
+ -rm -f pwg/$(am__dirstamp)
-rm -f seg/$(DEPDIR)/$(am__dirstamp)
-rm -f seg/$(am__dirstamp)
-rm -f suites/$(DEPDIR)/$(am__dirstamp)
@@ -1873,7 +1909,7 @@ clean-am: clean-checkPROGRAMS clean-generic clean-ipsecPROGRAMS \
clean-ipseclibLTLIBRARIES clean-libtool mostlyclean-am
distclean: distclean-recursive
- -rm -rf ./$(DEPDIR) ietf/$(DEPDIR) imc/$(DEPDIR) imv/$(DEPDIR) ita/$(DEPDIR) os_info/$(DEPDIR) pa_tnc/$(DEPDIR) pts/$(DEPDIR) pts/components/$(DEPDIR) pts/components/ita/$(DEPDIR) pts/components/tcg/$(DEPDIR) seg/$(DEPDIR) suites/$(DEPDIR) swid/$(DEPDIR) tcg/$(DEPDIR) tcg/pts/$(DEPDIR) tcg/seg/$(DEPDIR) tcg/swid/$(DEPDIR)
+ -rm -rf ./$(DEPDIR) generic/$(DEPDIR) ietf/$(DEPDIR) imc/$(DEPDIR) imv/$(DEPDIR) ita/$(DEPDIR) os_info/$(DEPDIR) pa_tnc/$(DEPDIR) pts/$(DEPDIR) pts/components/$(DEPDIR) pts/components/ita/$(DEPDIR) pts/components/tcg/$(DEPDIR) pwg/$(DEPDIR) seg/$(DEPDIR) suites/$(DEPDIR) swid/$(DEPDIR) tcg/$(DEPDIR) tcg/pts/$(DEPDIR) tcg/seg/$(DEPDIR) tcg/swid/$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
@@ -1920,7 +1956,7 @@ install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-recursive
- -rm -rf ./$(DEPDIR) ietf/$(DEPDIR) imc/$(DEPDIR) imv/$(DEPDIR) ita/$(DEPDIR) os_info/$(DEPDIR) pa_tnc/$(DEPDIR) pts/$(DEPDIR) pts/components/$(DEPDIR) pts/components/ita/$(DEPDIR) pts/components/tcg/$(DEPDIR) seg/$(DEPDIR) suites/$(DEPDIR) swid/$(DEPDIR) tcg/$(DEPDIR) tcg/pts/$(DEPDIR) tcg/seg/$(DEPDIR) tcg/swid/$(DEPDIR)
+ -rm -rf ./$(DEPDIR) generic/$(DEPDIR) ietf/$(DEPDIR) imc/$(DEPDIR) imv/$(DEPDIR) ita/$(DEPDIR) os_info/$(DEPDIR) pa_tnc/$(DEPDIR) pts/$(DEPDIR) pts/components/$(DEPDIR) pts/components/ita/$(DEPDIR) pts/components/tcg/$(DEPDIR) pwg/$(DEPDIR) seg/$(DEPDIR) suites/$(DEPDIR) swid/$(DEPDIR) tcg/$(DEPDIR) tcg/pts/$(DEPDIR) tcg/seg/$(DEPDIR) tcg/swid/$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
diff --git a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.c b/src/libimcv/generic/generic_attr_bool.c
index ee5864d29..3f570d9f8 100644
--- a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.c
+++ b/src/libimcv/generic/generic_attr_bool.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Andreas Steffen
+ * Copyright (C) 2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -13,36 +13,37 @@
* for more details.
*/
-#include "ietf_attr_default_pwd_enabled.h"
+#include "generic_attr_bool.h"
+#include <imcv.h>
#include <pa_tnc/pa_tnc_msg.h>
#include <bio/bio_writer.h>
#include <bio/bio_reader.h>
#include <utils/debug.h>
-typedef struct private_ietf_attr_default_pwd_enabled_t private_ietf_attr_default_pwd_enabled_t;
+typedef struct private_generic_attr_bool_t private_generic_attr_bool_t;
/**
- * PA-TNC Factory Default Password Enabled type (see section 4.2.12 of RFC 5792)
+ * Generic PA-TNC attribute containing boolean status value in 32 bit encoding
*
* 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
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * | Factory Default Password Enabled |
+ * | Boolean Value |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
-#define DEFAULT_PWD_ENABLED_SIZE 4
+#define ATTR_BOOL_SIZE 4
/**
- * Private data of an ietf_attr_default_pwd_enabled_t object.
+ * Private data of an generic_attr_bool_t object.
*/
-struct private_ietf_attr_default_pwd_enabled_t {
+struct private_generic_attr_bool_t {
/**
- * Public members of ietf_attr_default_pwd_enabled_t
+ * Public members of generic_attr_bool_t
*/
- ietf_attr_default_pwd_enabled_t public;
+ generic_attr_bool_t public;
/**
* Vendor-specific attribute type
@@ -65,7 +66,7 @@ struct private_ietf_attr_default_pwd_enabled_t {
bool noskip_flag;
/**
- * Factory Default Password Enabled status
+ * Boolean status value
*/
bool status;
@@ -76,31 +77,31 @@ struct private_ietf_attr_default_pwd_enabled_t {
};
METHOD(pa_tnc_attr_t, get_type, pen_type_t,
- private_ietf_attr_default_pwd_enabled_t *this)
+ private_generic_attr_bool_t *this)
{
return this->type;
}
METHOD(pa_tnc_attr_t, get_value, chunk_t,
- private_ietf_attr_default_pwd_enabled_t *this)
+ private_generic_attr_bool_t *this)
{
return this->value;
}
METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
- private_ietf_attr_default_pwd_enabled_t *this)
+ private_generic_attr_bool_t *this)
{
return this->noskip_flag;
}
METHOD(pa_tnc_attr_t, set_noskip_flag,void,
- private_ietf_attr_default_pwd_enabled_t *this, bool noskip)
+ private_generic_attr_bool_t *this, bool noskip)
{
this->noskip_flag = noskip;
}
METHOD(pa_tnc_attr_t, build, void,
- private_ietf_attr_default_pwd_enabled_t *this)
+ private_generic_attr_bool_t *this)
{
bio_writer_t *writer;
@@ -108,7 +109,7 @@ METHOD(pa_tnc_attr_t, build, void,
{
return;
}
- writer = bio_writer_create(DEFAULT_PWD_ENABLED_SIZE);
+ writer = bio_writer_create(ATTR_BOOL_SIZE);
writer->write_uint32(writer, this->status);
this->value = writer->extract_buf(writer);
@@ -117,31 +118,36 @@ METHOD(pa_tnc_attr_t, build, void,
}
METHOD(pa_tnc_attr_t, process, status_t,
- private_ietf_attr_default_pwd_enabled_t *this, u_int32_t *offset)
+ private_generic_attr_bool_t *this, u_int32_t *offset)
{
+ enum_name_t *pa_attr_names;
bio_reader_t *reader;
u_int32_t status;
-
+
*offset = 0;
if (this->value.len < this->length)
{
return NEED_MORE;
}
- if (this->value.len != DEFAULT_PWD_ENABLED_SIZE)
+ pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
+ this->type.vendor_id);
+
+ if (this->value.len != ATTR_BOOL_SIZE)
{
- DBG1(DBG_TNC, "incorrect size for IETF factory default password "
- "enabled attribute");
+ DBG1(DBG_TNC, "incorrect attribute size for %N/%N",
+ pen_names, this->type.vendor_id, pa_attr_names, this->type.type);
return FAILED;
}
reader = bio_reader_create(this->value);
reader->read_uint32(reader, &status);
reader->destroy(reader);
- if (status > TRUE)
+ if (status > 1)
{
- DBG1(DBG_TNC, "IETF factory default password enabled field "
- "has unknown value %u", status);
+ DBG1(DBG_TNC, "%N/%N attribute contains invalid non-boolean value %u",
+ pen_names, this->type.vendor_id, pa_attr_names, this->type.type,
+ status);
return FAILED;
}
this->status = status;
@@ -150,20 +156,20 @@ METHOD(pa_tnc_attr_t, process, status_t,
}
METHOD(pa_tnc_attr_t, add_segment, void,
- private_ietf_attr_default_pwd_enabled_t *this, chunk_t segment)
+ private_generic_attr_bool_t *this, chunk_t segment)
{
this->value = chunk_cat("mc", this->value, segment);
}
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
- private_ietf_attr_default_pwd_enabled_t *this)
+ private_generic_attr_bool_t *this)
{
ref_get(&this->ref);
return &this->public.pa_tnc_attribute;
}
METHOD(pa_tnc_attr_t, destroy, void,
- private_ietf_attr_default_pwd_enabled_t *this)
+ private_generic_attr_bool_t *this)
{
if (ref_put(&this->ref))
{
@@ -172,8 +178,8 @@ METHOD(pa_tnc_attr_t, destroy, void,
}
}
-METHOD(ietf_attr_default_pwd_enabled_t, get_status, bool,
- private_ietf_attr_default_pwd_enabled_t *this)
+METHOD(generic_attr_bool_t, get_status, bool,
+ private_generic_attr_bool_t *this)
{
return this->status;
}
@@ -181,9 +187,9 @@ METHOD(ietf_attr_default_pwd_enabled_t, get_status, bool,
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_default_pwd_enabled_create(bool status)
+pa_tnc_attr_t *generic_attr_bool_create(bool status, pen_type_t type)
{
- private_ietf_attr_default_pwd_enabled_t *this;
+ private_generic_attr_bool_t *this;
INIT(this,
.public = {
@@ -200,7 +206,7 @@ pa_tnc_attr_t *ietf_attr_default_pwd_enabled_create(bool status)
},
.get_status = _get_status,
},
- .type = { PEN_IETF, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED },
+ .type = type,
.status = status,
.ref = 1,
);
@@ -211,10 +217,10 @@ pa_tnc_attr_t *ietf_attr_default_pwd_enabled_create(bool status)
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_default_pwd_enabled_create_from_data(size_t length,
- chunk_t data)
+pa_tnc_attr_t *generic_attr_bool_create_from_data(size_t length, chunk_t data,
+ pen_type_t type)
{
- private_ietf_attr_default_pwd_enabled_t *this;
+ private_generic_attr_bool_t *this;
INIT(this,
.public = {
@@ -231,7 +237,7 @@ pa_tnc_attr_t *ietf_attr_default_pwd_enabled_create_from_data(size_t length,
},
.get_status = _get_status,
},
- .type = { PEN_IETF, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED },
+ .type = type,
.length = length,
.value = chunk_clone(data),
.ref = 1,
diff --git a/src/libimcv/generic/generic_attr_bool.h b/src/libimcv/generic/generic_attr_bool.h
new file mode 100644
index 000000000..93754bf9d
--- /dev/null
+++ b/src/libimcv/generic/generic_attr_bool.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 generic_attr_bool generic_attr_bool
+ * @{ @ingroup generic_attr
+ */
+
+#ifndef GENERIC_ATTR_BOOL_H_
+#define GENERIC_ATTR_BOOL_H_
+
+typedef struct generic_attr_bool_t generic_attr_bool_t;
+
+#include <pen/pen.h>
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing a generic PA-TNC attribute containing a boolean status
+ * value encoded as a 32 bit unsigned integer (0,1) in network order
+ */
+struct generic_attr_bool_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Gets boolean value
+ *
+ * @return Boolean status value
+ */
+ bool (*get_status)(generic_attr_bool_t *this);
+
+};
+
+/**
+ * Creates a generic_attr_bool_t object
+ *
+ * @param status Boolean status value
+ * @param type Vendor ID / Attribute Type
+ */
+pa_tnc_attr_t* generic_attr_bool_create(bool status, pen_type_t type);
+
+/**
+ * Creates an generic_attr_bool_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ * @param type Vendor ID / Attribute Type
+ */
+pa_tnc_attr_t* generic_attr_bool_create_from_data(size_t length, chunk_t value,
+ pen_type_t type);
+
+#endif /** GENERIC_ATTR_BOOL_H_ @}*/
diff --git a/src/libimcv/ita/ita_attr_device_id.c b/src/libimcv/generic/generic_attr_chunk.c
index 232842695..98a539987 100644
--- a/src/libimcv/ita/ita_attr_device_id.c
+++ b/src/libimcv/generic/generic_attr_chunk.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 Andreas Steffen
+ * Copyright (C) 2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -13,24 +13,23 @@
* for more details.
*/
-#include "ita_attr.h"
-#include "ita_attr_device_id.h"
+#include "generic_attr_chunk.h"
+#include <imcv.h>
#include <pen/pen.h>
-
#include <utils/debug.h>
-typedef struct private_ita_attr_device_id_t private_ita_attr_device_id_t;
+typedef struct private_generic_attr_chunk_t private_generic_attr_chunk_t;
/**
- * Private data of an ita_attr_device_id_t object.
+ * Private data of an generic_attr_chunk_t object.
*/
-struct private_ita_attr_device_id_t {
+struct private_generic_attr_chunk_t {
/**
- * Public members of ita_attr_device_id_t
+ * Public members of generic_attr_chunk_t
*/
- ita_attr_device_id_t public;
+ generic_attr_chunk_t public;
/**
* Vendor-specific attribute type
@@ -43,6 +42,11 @@ struct private_ita_attr_device_id_t {
size_t length;
/**
+ * Fixed size of attribute value, set to 0 if dynamic
+ */
+ size_t size;
+
+ /**
* Attribute value or segment
*/
chunk_t value;
@@ -59,62 +63,74 @@ struct private_ita_attr_device_id_t {
};
METHOD(pa_tnc_attr_t, get_type, pen_type_t,
- private_ita_attr_device_id_t *this)
+ private_generic_attr_chunk_t *this)
{
return this->type;
}
METHOD(pa_tnc_attr_t, get_value, chunk_t,
- private_ita_attr_device_id_t *this)
+ private_generic_attr_chunk_t *this)
{
return this->value;
}
METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
- private_ita_attr_device_id_t *this)
+ private_generic_attr_chunk_t *this)
{
return this->noskip_flag;
}
METHOD(pa_tnc_attr_t, set_noskip_flag,void,
- private_ita_attr_device_id_t *this, bool noskip)
+ private_generic_attr_chunk_t *this, bool noskip)
{
this->noskip_flag = noskip;
}
METHOD(pa_tnc_attr_t, build, void,
- private_ita_attr_device_id_t *this)
+ private_generic_attr_chunk_t *this)
{
return;
}
METHOD(pa_tnc_attr_t, process, status_t,
- private_ita_attr_device_id_t *this, u_int32_t *offset)
+ private_generic_attr_chunk_t *this, u_int32_t *offset)
{
+ enum_name_t *pa_attr_names;
*offset = 0;
if (this->value.len < this->length)
{
return NEED_MORE;
}
+ pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
+ this->type.vendor_id);
+
+ if ((this->size == 0 && this->value.len > this->length) ||
+ (this->size != 0 && this->value.len != this->size))
+ {
+ DBG1(DBG_TNC, "inconsistent length of %N/%N string attribute",
+ pen_names, this->type.vendor_id, pa_attr_names, this->type.type);
+ return FAILED;
+ }
+
return SUCCESS;
}
METHOD(pa_tnc_attr_t, add_segment, void,
- private_ita_attr_device_id_t *this, chunk_t segment)
+ private_generic_attr_chunk_t *this, chunk_t segment)
{
this->value = chunk_cat("mc", this->value, segment);
}
METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
- private_ita_attr_device_id_t *this)
+ private_generic_attr_chunk_t *this)
{
ref_get(&this->ref);
return &this->public.pa_tnc_attribute;
}
METHOD(pa_tnc_attr_t, destroy, void,
- private_ita_attr_device_id_t *this)
+ private_generic_attr_chunk_t *this)
{
if (ref_put(&this->ref))
{
@@ -126,9 +142,10 @@ METHOD(pa_tnc_attr_t, destroy, void,
/**
* Described in header.
*/
-pa_tnc_attr_t *ita_attr_device_id_create_from_data(size_t length, chunk_t value)
+pa_tnc_attr_t *generic_attr_chunk_create_from_data(size_t length, chunk_t value,
+ size_t size, pen_type_t type)
{
- private_ita_attr_device_id_t *this;
+ private_generic_attr_chunk_t *this;
INIT(this,
.public = {
@@ -144,8 +161,9 @@ pa_tnc_attr_t *ita_attr_device_id_create_from_data(size_t length, chunk_t value)
.destroy = _destroy,
},
},
- .type = { PEN_ITA, ITA_ATTR_DEVICE_ID },
+ .type = type,
.length = length,
+ .size = size,
.value = chunk_clone(value),
.ref = 1,
);
@@ -156,8 +174,9 @@ pa_tnc_attr_t *ita_attr_device_id_create_from_data(size_t length, chunk_t value)
/**
* Described in header.
*/
-pa_tnc_attr_t *ita_attr_device_id_create(chunk_t value)
+pa_tnc_attr_t *generic_attr_chunk_create(chunk_t value, pen_type_t type)
{
- return ita_attr_device_id_create_from_data(value.len, value);
+ return generic_attr_chunk_create_from_data(value.len, value,
+ value.len, type);
}
diff --git a/src/libimcv/generic/generic_attr_chunk.h b/src/libimcv/generic/generic_attr_chunk.h
new file mode 100644
index 000000000..a9b3a62de
--- /dev/null
+++ b/src/libimcv/generic/generic_attr_chunk.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 generic_attr_chunk generic_attr_chunk
+ * @{ @ingroup generic_attr
+ */
+
+#ifndef GENERIC_ATTR_CHUNK_H_
+#define GENERIC_ATTR_CHUNK_H_
+
+typedef struct generic_attr_chunk_t generic_attr_chunk_t;
+
+#include <pen/pen.h>
+#include "pa_tnc/pa_tnc_attr.h"
+
+/**
+ * Class implementing a generic PA-TNC attribute containing a possibly
+ * binary string with either a fixed or variable size
+ */
+struct generic_attr_chunk_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+};
+
+/**
+ * Creates a generic_attr_chunk_t object
+ *
+ * @param string Non-nul terminated string
+ * @param type Vendor ID / Attribute Type
+ */
+pa_tnc_attr_t* generic_attr_chunk_create(chunk_t string, pen_type_t type);
+
+/**
+ * Creates an generic_attr_chunk_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ * @param size size in bytes if fixed array or 0 if dynamic size
+ * @param type Vendor ID / Attribute Type
+ */
+pa_tnc_attr_t* generic_attr_chunk_create_from_data(size_t length, chunk_t value,
+ size_t size, pen_type_t type);
+
+#endif /** GENERIC_ATTR_CHUNK_H_ @}*/
diff --git a/src/libimcv/generic/generic_attr_string.c b/src/libimcv/generic/generic_attr_string.c
new file mode 100644
index 000000000..e63c0126a
--- /dev/null
+++ b/src/libimcv/generic/generic_attr_string.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2013-2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 "generic_attr_string.h"
+
+#include <imcv.h>
+#include <pen/pen.h>
+#include <utils/debug.h>
+
+typedef struct private_generic_attr_string_t private_generic_attr_string_t;
+
+/**
+ * Private data of an generic_attr_string_t object.
+ */
+struct private_generic_attr_string_t {
+
+ /**
+ * Public members of generic_attr_string_t
+ */
+ generic_attr_string_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_generic_attr_string_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_generic_attr_string_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_generic_attr_string_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_generic_attr_string_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_generic_attr_string_t *this)
+{
+ return;
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_generic_attr_string_t *this, u_int32_t *offset)
+{
+ enum_name_t *pa_attr_names;
+ u_char *pos;
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ pa_attr_names = imcv_pa_tnc_attributes->get_names(imcv_pa_tnc_attributes,
+ this->type.vendor_id);
+ if (this->value.len > this->length)
+ {
+ DBG1(DBG_TNC, "inconsistent length of %N/%N string attribute",
+ pen_names, this->type.vendor_id, pa_attr_names, this->type.type);
+ return FAILED;
+ }
+
+ pos = memchr(this->value.ptr, '\0', this->value.len);
+ if (pos)
+ {
+ DBG1(DBG_TNC, "nul termination in %N/%N string attribute",
+ pen_names, this->type.vendor_id, pa_attr_names, this->type.type);
+ *offset = pos - this->value.ptr;
+ return FAILED;
+ }
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_generic_attr_string_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_generic_attr_string_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_generic_attr_string_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *generic_attr_string_create_from_data(size_t length,
+ chunk_t value, pen_type_t type)
+{
+ private_generic_attr_string_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ },
+ .type = type,
+ .length = length,
+ .value = chunk_clone(value),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *generic_attr_string_create(chunk_t value, pen_type_t type)
+{
+ return generic_attr_string_create_from_data(value.len, value, type);
+}
+
diff --git a/src/libimcv/ita/ita_attr_device_id.h b/src/libimcv/generic/generic_attr_string.h
index 94bb778c0..d830ab4aa 100644
--- a/src/libimcv/ita/ita_attr_device_id.h
+++ b/src/libimcv/generic/generic_attr_string.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 Andreas Steffen
+ * Copyright (C) 2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,43 +14,46 @@
*/
/**
- * @defgroup ita_attr_device_id ita_attr_device_id
- * @{ @ingroup ita_attr
+ * @defgroup generic_attr_string generic_attr_string
+ * @{ @ingroup generic_attr
*/
-#ifndef ITA_ATTR_DEVICE_ID_H_
-#define ITA_ATTR_DEVICE_ID_H_
+#ifndef GENERIC_ATTR_STRING_H_
+#define GENERIC_ATTR_STRING_H_
-typedef struct ita_attr_device_id_t ita_attr_device_id_t;
+typedef struct generic_attr_string_t generic_attr_string_t;
+#include <pen/pen.h>
#include "pa_tnc/pa_tnc_attr.h"
/**
- * Class implementing the ITA Device ID PA-TNC attribute.
- *
+ * Class implementing a generic PA-TNC attribute containing a non-nul
+ * terminated printable string
*/
-struct ita_attr_device_id_t {
+struct generic_attr_string_t {
/**
* Public PA-TNC attribute interface
*/
pa_tnc_attr_t pa_tnc_attribute;
-
};
/**
- * Creates an ita_attr_device_id_t object
+ * Creates a generic_attr_string_t object
*
- * @param value ITA Device ID attribute value
+ * @param string Non-nul terminated string
+ * @param type Vendor ID / Attribute Type
*/
-pa_tnc_attr_t* ita_attr_device_id_create(chunk_t value);
+pa_tnc_attr_t* generic_attr_string_create(chunk_t string, pen_type_t type);
/**
- * Creates an ita_attr_device_id_t object from received data
+ * Creates an generic_attr_string_t object from received data
*
* @param length Total length of attribute value
* @param value Unparsed attribute value (might be a segment)
+ * @param type Vendor ID / Attribute Type
*/
-pa_tnc_attr_t* ita_attr_device_id_create_from_data(size_t length, chunk_t value);
+pa_tnc_attr_t* generic_attr_string_create_from_data(size_t length,
+ chunk_t value, pen_type_t type);
-#endif /** ITA_ATTR_DEVICE_ID_H_ @}*/
+#endif /** GENERIC_ATTR_STRING_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr.c b/src/libimcv/ietf/ietf_attr.c
index 67269af53..38b777fce 100644
--- a/src/libimcv/ietf/ietf_attr.c
+++ b/src/libimcv/ietf/ietf_attr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2014 Andreas Steffen
+ * Copyright (C) 2011-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -17,7 +17,6 @@
#include "ietf/ietf_attr_assess_result.h"
#include "ietf/ietf_attr_attr_request.h"
#include "ietf/ietf_attr_fwd_enabled.h"
-#include "ietf/ietf_attr_default_pwd_enabled.h"
#include "ietf/ietf_attr_installed_packages.h"
#include "ietf/ietf_attr_numeric_version.h"
#include "ietf/ietf_attr_op_status.h"
@@ -26,6 +25,7 @@
#include "ietf/ietf_attr_product_info.h"
#include "ietf/ietf_attr_remediation_instr.h"
#include "ietf/ietf_attr_string_version.h"
+#include "generic/generic_attr_bool.h"
ENUM(ietf_attr_names, IETF_ATTR_TESTING, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED,
@@ -63,7 +63,8 @@ pa_tnc_attr_t* ietf_attr_create_from_data(u_int32_t type, size_t length,
case IETF_ATTR_OPERATIONAL_STATUS:
return ietf_attr_op_status_create_from_data(length, value);
case IETF_ATTR_PORT_FILTER:
- return ietf_attr_port_filter_create_from_data(length, value);
+ return ietf_attr_port_filter_create_from_data(length, value,
+ pen_type_create(PEN_IETF, type));
case IETF_ATTR_INSTALLED_PACKAGES:
return ietf_attr_installed_packages_create_from_data(length, value);
case IETF_ATTR_PA_TNC_ERROR:
@@ -73,9 +74,11 @@ pa_tnc_attr_t* ietf_attr_create_from_data(u_int32_t type, size_t length,
case IETF_ATTR_REMEDIATION_INSTRUCTIONS:
return ietf_attr_remediation_instr_create_from_data(length, value);
case IETF_ATTR_FORWARDING_ENABLED:
- return ietf_attr_fwd_enabled_create_from_data(length, value);
+ return ietf_attr_fwd_enabled_create_from_data(length, value,
+ pen_type_create(PEN_IETF, type));
case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED:
- return ietf_attr_default_pwd_enabled_create_from_data(length, value);
+ return generic_attr_bool_create_from_data(length, value,
+ pen_type_create(PEN_IETF, type));
case IETF_ATTR_TESTING:
case IETF_ATTR_RESERVED:
default:
diff --git a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h b/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h
deleted file mode 100644
index 3999590d4..000000000
--- a/src/libimcv/ietf/ietf_attr_default_pwd_enabled.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2012 Andreas Steffen
- * HSR Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * 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 ietf_attr_default_pwd_enabled ietf_attr_default_pwd_enabled
- * @{ @ingroup ietf_attr
- */
-
-#ifndef IETF_ATTR_PWD_ENABLED_H_
-#define IETF_ATTR_PWD_ENABLED_H_
-
-typedef struct ietf_attr_default_pwd_enabled_t ietf_attr_default_pwd_enabled_t;
-
-#include "ietf_attr.h"
-#include "pa_tnc/pa_tnc_attr.h"
-
-/**
- * Class implementing the IETF PA-TNC Factory Default Password Enabled attribute.
- *
- */
-struct ietf_attr_default_pwd_enabled_t {
-
- /**
- * Public PA-TNC attribute interface
- */
- pa_tnc_attr_t pa_tnc_attribute;
-
- /**
- * Gets the Factory Default Password Enabled status
- *
- * @return Factory Default Password Enabled status
- */
- bool (*get_status)(ietf_attr_default_pwd_enabled_t *this);
-
-};
-
-/**
- * Creates an ietf_attr_default_pwd_enabled_t object
- *
- * @param status Factory Default Password Enabled status
- */
-pa_tnc_attr_t* ietf_attr_default_pwd_enabled_create(bool status);
-
-/**
- * Creates an ietf_attr_default_pwd_enabled_t object from received data
- *
- * @param length Total length of attribute value
- * @param value Unparsed attribute value (might be a segment)
- */
-pa_tnc_attr_t* ietf_attr_default_pwd_enabled_create_from_data(size_t length,
- chunk_t value);
-
-#endif /** IETF_ATTR_PWD_ENABLED_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_fwd_enabled.c b/src/libimcv/ietf/ietf_attr_fwd_enabled.c
index c00a5efc2..876a740c0 100644
--- a/src/libimcv/ietf/ietf_attr_fwd_enabled.c
+++ b/src/libimcv/ietf/ietf_attr_fwd_enabled.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Andreas Steffen
+ * Copyright (C) 2012-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -180,7 +180,8 @@ METHOD(ietf_attr_fwd_enabled_t, get_status, os_fwd_status_t,
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_fwd_enabled_create(os_fwd_status_t fwd_status)
+pa_tnc_attr_t *ietf_attr_fwd_enabled_create(os_fwd_status_t fwd_status,
+ pen_type_t type)
{
private_ietf_attr_fwd_enabled_t *this;
@@ -199,7 +200,7 @@ pa_tnc_attr_t *ietf_attr_fwd_enabled_create(os_fwd_status_t fwd_status)
},
.get_status = _get_status,
},
- .type = { PEN_IETF, IETF_ATTR_FORWARDING_ENABLED },
+ .type = type,
.fwd_status = fwd_status,
.ref = 1,
);
@@ -211,7 +212,7 @@ pa_tnc_attr_t *ietf_attr_fwd_enabled_create(os_fwd_status_t fwd_status)
* Described in header.
*/
pa_tnc_attr_t *ietf_attr_fwd_enabled_create_from_data(size_t length,
- chunk_t data)
+ chunk_t data, pen_type_t type)
{
private_ietf_attr_fwd_enabled_t *this;
@@ -230,7 +231,7 @@ pa_tnc_attr_t *ietf_attr_fwd_enabled_create_from_data(size_t length,
},
.get_status = _get_status,
},
- .type = { PEN_IETF, IETF_ATTR_FORWARDING_ENABLED },
+ .type = type,
.length = length,
.value = chunk_clone(data),
.ref = 1,
diff --git a/src/libimcv/ietf/ietf_attr_fwd_enabled.h b/src/libimcv/ietf/ietf_attr_fwd_enabled.h
index 3d554369b..39abb0a03 100644
--- a/src/libimcv/ietf/ietf_attr_fwd_enabled.h
+++ b/src/libimcv/ietf/ietf_attr_fwd_enabled.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Andreas Steffen
+ * Copyright (C) 2012-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -51,16 +51,19 @@ struct ietf_attr_fwd_enabled_t {
* Creates an ietf_attr_fwd_enabled_t object
*
* @param fwd_status Forwarding Enabled status
+ * @param type Vendor ID / Attribute Type
*/
-pa_tnc_attr_t* ietf_attr_fwd_enabled_create(os_fwd_status_t fwd_status);
+pa_tnc_attr_t* ietf_attr_fwd_enabled_create(os_fwd_status_t fwd_status,
+ pen_type_t type);
/**
* Creates an ietf_attr_fwd_enabled_t object from received data
*
* @param length Total length of attribute value
* @param value Unparsed attribute value (might be a segment)
+ * @param type Vendor ID / Attribute Type
*/
pa_tnc_attr_t* ietf_attr_fwd_enabled_create_from_data(size_t length,
- chunk_t value);
+ chunk_t value, pen_type_t type);
#endif /** IETF_ATTR_FWD_ENABLED_H_ @}*/
diff --git a/src/libimcv/ietf/ietf_attr_port_filter.c b/src/libimcv/ietf/ietf_attr_port_filter.c
index 46824406a..6f7ff54cc 100644
--- a/src/libimcv/ietf/ietf_attr_port_filter.c
+++ b/src/libimcv/ietf/ietf_attr_port_filter.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2014 Andreas Steffen
+ * Copyright (C) 2011-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -236,7 +236,7 @@ METHOD(ietf_attr_port_filter_t, create_port_enumerator, enumerator_t*,
/**
* Described in header.
*/
-pa_tnc_attr_t *ietf_attr_port_filter_create(void)
+pa_tnc_attr_t *ietf_attr_port_filter_create(pen_type_t type)
{
private_ietf_attr_port_filter_t *this;
@@ -256,7 +256,7 @@ pa_tnc_attr_t *ietf_attr_port_filter_create(void)
.add_port = _add_port,
.create_port_enumerator = _create_port_enumerator,
},
- .type = { PEN_IETF, IETF_ATTR_PORT_FILTER },
+ .type = type,
.ports = linked_list_create(),
.ref = 1,
);
@@ -268,7 +268,7 @@ pa_tnc_attr_t *ietf_attr_port_filter_create(void)
* Described in header.
*/
pa_tnc_attr_t *ietf_attr_port_filter_create_from_data(size_t length,
- chunk_t data)
+ chunk_t data, pen_type_t type)
{
private_ietf_attr_port_filter_t *this;
@@ -288,7 +288,7 @@ pa_tnc_attr_t *ietf_attr_port_filter_create_from_data(size_t length,
.add_port = _add_port,
.create_port_enumerator = _create_port_enumerator,
},
- .type = {PEN_IETF, IETF_ATTR_PORT_FILTER },
+ .type = type,
.length = length,
.value = chunk_clone(data),
.ports = linked_list_create(),
diff --git a/src/libimcv/ietf/ietf_attr_port_filter.h b/src/libimcv/ietf/ietf_attr_port_filter.h
index d383b19a2..e6c5a3f61 100644
--- a/src/libimcv/ietf/ietf_attr_port_filter.h
+++ b/src/libimcv/ietf/ietf_attr_port_filter.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2014 Andreas Steffen
+ * Copyright (C) 2011-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -61,16 +61,18 @@ struct ietf_attr_port_filter_t {
/**
* Creates an ietf_attr_port_filter_t object
*
+ * @param type Vendor ID / Attribute Type
*/
-pa_tnc_attr_t* ietf_attr_port_filter_create(void);
+pa_tnc_attr_t* ietf_attr_port_filter_create(pen_type_t type);
/**
* Creates an ietf_attr_port_filter_t object from received data
*
* @param length Total length of attribute value
* @param value Unparsed attribute value (might be a segment)
+ * @param type Vendor ID / Attribute Type
*/
pa_tnc_attr_t* ietf_attr_port_filter_create_from_data(size_t length,
- chunk_t value);
+ chunk_t value, pen_type_t type);
#endif /** IETF_ATTR_PORT_FILTER_H_ @}*/
diff --git a/src/libimcv/imc/imc_msg.c b/src/libimcv/imc/imc_msg.c
index 83337cf7b..9e12e29f1 100644
--- a/src/libimcv/imc/imc_msg.c
+++ b/src/libimcv/imc/imc_msg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Andreas Steffen
+ * Copyright (C) 2012-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -108,6 +108,7 @@ METHOD(imc_msg_t, send_, TNC_Result,
pa_tnc_attr_t *attr;
TNC_UInt32 msg_flags;
TNC_MessageType msg_type;
+ size_t max_msg_len, min_seg_attr_len, space_left;
bool attr_added, oversize;
chunk_t msg;
seg_contract_t *contract;
@@ -120,23 +121,37 @@ METHOD(imc_msg_t, send_, TNC_Result,
contract = contracts->get_contract(contracts, this->msg_type,
FALSE, this->dst_id);
+ /* Retrieve maximum allowed PA-TNC message size if set */
+ max_msg_len = this->state->get_max_msg_len(this->state);
+
+ /* Minimum size needed for Segmentation Envelope Attribute */
+ min_seg_attr_len = PA_TNC_ATTR_HEADER_SIZE + TCG_SEG_ATTR_SEG_ENV_HEADER +
+ PA_TNC_ATTR_HEADER_SIZE;
+
while (this->attr_list->get_count(this->attr_list))
{
- pa_tnc_msg = pa_tnc_msg_create(this->state->get_max_msg_len(this->state));
+ pa_tnc_msg = pa_tnc_msg_create(max_msg_len);
attr_added = FALSE;
enumerator = this->attr_list->create_enumerator(this->attr_list);
while (enumerator->enumerate(enumerator, &attr))
{
+ space_left = pa_tnc_msg->get_space(pa_tnc_msg);
+
if (contract && contract->check_size(contract, attr, &oversize))
{
if (oversize)
{
- /* TODO generate SWID error msg */
+ /* TODO handle oversized attributes */
+ }
+ else if (max_msg_len == 0 || space_left >= min_seg_attr_len)
+ {
+ attr = contract->first_segment(contract, attr, space_left);
}
else
{
- attr = contract->first_segment(contract, attr);
+ /* segment attribute in next iteration */
+ break;
}
}
if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr))
@@ -147,11 +162,12 @@ METHOD(imc_msg_t, send_, TNC_Result,
{
if (attr_added)
{
+ /* there might be space for attribute in next iteration */
break;
}
else
{
- DBG1(DBG_IMC, "PA-TNC attribute too large to send, deleted");
+ DBG1(DBG_IMV, "PA-TNC attribute too large to send, deleted");
attr->destroy(attr);
}
}
@@ -341,9 +357,7 @@ METHOD(imc_msg_t, receive, TNC_Result,
my_max_seg_size = this->state->get_max_msg_len(this->state)
- PA_TNC_HEADER_SIZE
- PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_SEG_ENV_HEADER
- - PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+ - TCG_SEG_ATTR_SEG_ENV_HEADER;
/* If segmentation is possible select lower segment size */
if (max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
diff --git a/src/libimcv/imc/imc_os_info.c b/src/libimcv/imc/imc_os_info.c
index 47697f1a3..0a094eb23 100644
--- a/src/libimcv/imc/imc_os_info.c
+++ b/src/libimcv/imc/imc_os_info.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Andreas Steffen
+ * Copyright (C) 2012-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -90,6 +90,14 @@ METHOD(imc_os_info_t, get_version, chunk_t,
return this->version;
}
+METHOD(imc_os_info_t, get_default_pwd_status, bool,
+ private_imc_os_info_t *this)
+{
+ /* As an option the default password status can be configured manually */
+ return lib->settings->get_bool(lib->settings,
+ "%s.imcv.os_info.default_password_enabled", FALSE, lib->ns);
+}
+
#ifdef WIN32
METHOD(imc_os_info_t, get_fwd_status, os_fwd_status_t,
@@ -618,6 +626,7 @@ imc_os_info_t *imc_os_info_create(void)
.get_numeric_version = _get_numeric_version,
.get_version = _get_version,
.get_fwd_status = _get_fwd_status,
+ .get_default_pwd_status = _get_default_pwd_status,
.get_uptime = _get_uptime,
.get_setting = _get_setting,
.create_package_enumerator = _create_package_enumerator,
diff --git a/src/libimcv/imc/imc_os_info.h b/src/libimcv/imc/imc_os_info.h
index 6bb0e960c..ef7fb6d43 100644
--- a/src/libimcv/imc/imc_os_info.h
+++ b/src/libimcv/imc/imc_os_info.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Andreas Steffen
+ * Copyright (C) 2012-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -72,6 +72,13 @@ struct imc_os_info_t {
os_fwd_status_t (*get_fwd_status)(imc_os_info_t *this);
/**
+ * Get the default password status
+ *
+ * @return TRUE if enabled, FALSE otherwise
+ */
+ bool (*get_default_pwd_status)(imc_os_info_t *this);
+
+ /**
* Get the OS uptime in seconds
*
* @return OS uptime
diff --git a/src/libimcv/imcv.c b/src/libimcv/imcv.c
index bd4156c19..ec6ea4288 100644
--- a/src/libimcv/imcv.c
+++ b/src/libimcv/imcv.c
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -15,6 +16,7 @@
#include "imcv.h"
#include "ietf/ietf_attr.h"
#include "ita/ita_attr.h"
+#include "pwg/pwg_attr.h"
#include "tcg/tcg_attr.h"
#include "pts/components/pts_component.h"
#include "pts/components/pts_component_manager.h"
@@ -179,6 +181,8 @@ bool libimcv_init(bool is_imv)
ietf_attr_create_from_data, ietf_attr_names);
imcv_pa_tnc_attributes->add_vendor(imcv_pa_tnc_attributes, PEN_ITA,
ita_attr_create_from_data, ita_attr_names);
+ imcv_pa_tnc_attributes->add_vendor(imcv_pa_tnc_attributes, PEN_PWG,
+ pwg_attr_create_from_data, pwg_attr_names);
imcv_pa_tnc_attributes->add_vendor(imcv_pa_tnc_attributes, PEN_TCG,
tcg_attr_create_from_data, tcg_attr_names);
@@ -235,6 +239,7 @@ void libimcv_deinit(void)
imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_IETF);
imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_ITA);
+ imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_PWG);
imcv_pa_tnc_attributes->remove_vendor(imcv_pa_tnc_attributes, PEN_TCG);
DESTROY_IF(imcv_pa_tnc_attributes);
imcv_pa_tnc_attributes = NULL;
diff --git a/src/libimcv/imcv.h b/src/libimcv/imcv.h
index 31536eca5..e260ff8f6 100644
--- a/src/libimcv/imcv.h
+++ b/src/libimcv/imcv.h
@@ -15,6 +15,9 @@
/**
* @defgroup libimcv libimcv
*
+ * @defgroup generic_attr generic_attr
+ * @ingroup libimcv
+ *
* @defgroup libimcv_imc imc
* @ingroup libimcv
*
diff --git a/src/libimcv/imv/imv_msg.c b/src/libimcv/imv/imv_msg.c
index fdf63325d..039124c2a 100644
--- a/src/libimcv/imv/imv_msg.c
+++ b/src/libimcv/imv/imv_msg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 Andreas Steffen
+ * Copyright (C) 2012-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -125,6 +125,7 @@ METHOD(imv_msg_t, send_, TNC_Result,
pa_tnc_attr_t *attr;
TNC_UInt32 msg_flags;
TNC_MessageType msg_type;
+ size_t max_msg_len, min_seg_attr_len, space_left;
bool attr_added, oversize;
chunk_t msg;
seg_contract_t *contract;
@@ -137,23 +138,37 @@ METHOD(imv_msg_t, send_, TNC_Result,
contract = contracts->get_contract(contracts, this->msg_type,
FALSE, this->dst_id);
+ /* Retrieve maximum allowed PA-TNC message size if set */
+ max_msg_len = this->state->get_max_msg_len(this->state);
+
+ /* Minimum size needed for Segmentation Envelope Attribute */
+ min_seg_attr_len = PA_TNC_ATTR_HEADER_SIZE + TCG_SEG_ATTR_SEG_ENV_HEADER +
+ PA_TNC_ATTR_HEADER_SIZE;
+
while (this->attr_list->get_count(this->attr_list))
{
- pa_tnc_msg = pa_tnc_msg_create(this->state->get_max_msg_len(this->state));
+ pa_tnc_msg = pa_tnc_msg_create(max_msg_len);
attr_added = FALSE;
enumerator = this->attr_list->create_enumerator(this->attr_list);
while (enumerator->enumerate(enumerator, &attr))
{
+ space_left = pa_tnc_msg->get_space(pa_tnc_msg);
+
if (contract && contract->check_size(contract, attr, &oversize))
{
if (oversize)
{
- /* TODO generate SWID error msg */
+ /* TODO handle oversized attributes */
+ }
+ else if (max_msg_len == 0 || space_left >= min_seg_attr_len)
+ {
+ attr = contract->first_segment(contract, attr, space_left);
}
else
{
- attr = contract->first_segment(contract, attr);
+ /* segment attribute in next iteration */
+ break;
}
}
if (pa_tnc_msg->add_attribute(pa_tnc_msg, attr))
@@ -164,6 +179,7 @@ METHOD(imv_msg_t, send_, TNC_Result,
{
if (attr_added)
{
+ /* there might be space for attribute in next iteration */
break;
}
else
@@ -377,9 +393,7 @@ METHOD(imv_msg_t, receive, TNC_Result,
my_max_seg_size = this->state->get_max_msg_len(this->state)
- PA_TNC_HEADER_SIZE
- PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_SEG_ENV_HEADER
- - PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+ - TCG_SEG_ATTR_SEG_ENV_HEADER;
/* If segmentation is possible select lower segment size */
if (max_seg_size != SEG_CONTRACT_NO_FRAGMENTATION &&
diff --git a/src/libimcv/ita/ita_attr.c b/src/libimcv/ita/ita_attr.c
index 9d7706dba..35c882c37 100644
--- a/src/libimcv/ita/ita_attr.c
+++ b/src/libimcv/ita/ita_attr.c
@@ -19,7 +19,7 @@
#include "ita/ita_attr_get_settings.h"
#include "ita/ita_attr_settings.h"
#include "ita/ita_attr_angel.h"
-#include "ita/ita_attr_device_id.h"
+#include "generic/generic_attr_string.h"
ENUM(ita_attr_names, ITA_ATTR_COMMAND, ITA_ATTR_DEVICE_ID,
"Command",
@@ -53,7 +53,8 @@ pa_tnc_attr_t* ita_attr_create_from_data(u_int32_t type, size_t length,
case ITA_ATTR_STOP_ANGEL:
return ita_attr_angel_create_from_data(FALSE);
case ITA_ATTR_DEVICE_ID:
- return ita_attr_device_id_create_from_data(length, value);
+ return generic_attr_string_create_from_data(length, value,
+ pen_type_create(PEN_ITA, type));
default:
return NULL;
}
diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.c b/src/libimcv/pa_tnc/pa_tnc_msg.c
index ea4dee950..17c649dfd 100644
--- a/src/libimcv/pa_tnc/pa_tnc_msg.c
+++ b/src/libimcv/pa_tnc/pa_tnc_msg.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2014 Andreas Steffen
+ * Copyright (C) 2011-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -92,6 +92,12 @@ METHOD(pa_tnc_msg_t, get_encoding, chunk_t,
return this->encoding;
}
+METHOD(pa_tnc_msg_t, get_space, size_t,
+ private_pa_tnc_msg_t *this)
+{
+ return this->max_msg_len ? this->max_msg_len - this->msg_len : 0;
+}
+
METHOD(pa_tnc_msg_t, add_attribute, bool,
private_pa_tnc_msg_t *this, pa_tnc_attr_t *attr)
{
@@ -389,6 +395,7 @@ pa_tnc_msg_t *pa_tnc_msg_create(size_t max_msg_len)
INIT(this,
.public = {
.get_encoding = _get_encoding,
+ .get_space = _get_space,
.add_attribute = _add_attribute,
.build = _build,
.process = _process,
@@ -416,6 +423,7 @@ pa_tnc_msg_t *pa_tnc_msg_create_from_data(chunk_t data)
INIT(this,
.public = {
.get_encoding = _get_encoding,
+ .get_space = _get_space,
.add_attribute = _add_attribute,
.build = _build,
.process = _process,
diff --git a/src/libimcv/pa_tnc/pa_tnc_msg.h b/src/libimcv/pa_tnc/pa_tnc_msg.h
index 57ff1a04c..3be302032 100644
--- a/src/libimcv/pa_tnc/pa_tnc_msg.h
+++ b/src/libimcv/pa_tnc/pa_tnc_msg.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2014 Andreas Steffen
+ * Copyright (C) 2011-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -44,6 +44,13 @@ struct pa_tnc_msg_t {
chunk_t (*get_encoding)(pa_tnc_msg_t *this);
/**
+ * Get the remaining space in octets left in the PA-TNC message
+ *
+ * @return remaining space or 0 if max_msg_len is not set
+ */
+ size_t (*get_space)(pa_tnc_msg_t *this);
+
+ /**
* Add a PA-TNC attribute
*
* @param attr PA-TNC attribute to be addedd
diff --git a/src/libimcv/plugins/imc_hcd/Makefile.am b/src/libimcv/plugins/imc_hcd/Makefile.am
new file mode 100644
index 000000000..db25a57de
--- /dev/null
+++ b/src/libimcv/plugins/imc_hcd/Makefile.am
@@ -0,0 +1,16 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libimcv
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+imcv_LTLIBRARIES = imc-hcd.la
+
+imc_hcd_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+imc_hcd_la_SOURCES = imc_hcd.c imc_hcd_state.h imc_hcd_state.c
+
+imc_hcd_la_LDFLAGS = -module -avoid-version -no-undefined
diff --git a/src/libimcv/plugins/imc_hcd/Makefile.in b/src/libimcv/plugins/imc_hcd/Makefile.in
new file mode 100644
index 000000000..da7523c33
--- /dev/null
+++ b/src/libimcv/plugins/imc_hcd/Makefile.in
@@ -0,0 +1,763 @@
+# 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/libimcv/plugins/imc_hcd
+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)$(imcvdir)"
+LTLIBRARIES = $(imcv_LTLIBRARIES)
+imc_hcd_la_DEPENDENCIES = $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+am_imc_hcd_la_OBJECTS = imc_hcd.lo imc_hcd_state.lo
+imc_hcd_la_OBJECTS = $(am_imc_hcd_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 =
+imc_hcd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imc_hcd_la_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(imc_hcd_la_SOURCES)
+DIST_SOURCES = $(imc_hcd_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libimcv
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+imcv_LTLIBRARIES = imc-hcd.la
+imc_hcd_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+imc_hcd_la_SOURCES = imc_hcd.c imc_hcd_state.h imc_hcd_state.c
+imc_hcd_la_LDFLAGS = -module -avoid-version -no-undefined
+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/libimcv/plugins/imc_hcd/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libimcv/plugins/imc_hcd/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):
+
+install-imcvLTLIBRARIES: $(imcv_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(imcv_LTLIBRARIES)'; test -n "$(imcvdir)" || 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)$(imcvdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(imcvdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(imcvdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(imcvdir)"; \
+ }
+
+uninstall-imcvLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(imcv_LTLIBRARIES)'; test -n "$(imcvdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(imcvdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(imcvdir)/$$f"; \
+ done
+
+clean-imcvLTLIBRARIES:
+ -test -z "$(imcv_LTLIBRARIES)" || rm -f $(imcv_LTLIBRARIES)
+ @list='$(imcv_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}; \
+ }
+
+imc-hcd.la: $(imc_hcd_la_OBJECTS) $(imc_hcd_la_DEPENDENCIES) $(EXTRA_imc_hcd_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imc_hcd_la_LINK) -rpath $(imcvdir) $(imc_hcd_la_OBJECTS) $(imc_hcd_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imc_hcd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imc_hcd_state.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)$(imcvdir)"; 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-imcvLTLIBRARIES clean-libtool \
+ 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-imcvLTLIBRARIES
+
+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-imcvLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-imcvLTLIBRARIES clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am \
+ install-imcvLTLIBRARIES install-info install-info-am \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-imcvLTLIBRARIES
+
+
+# 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/libimcv/plugins/imc_hcd/imc_hcd.c b/src/libimcv/plugins/imc_hcd/imc_hcd.c
new file mode 100644
index 000000000..b631683ce
--- /dev/null
+++ b/src/libimcv/plugins/imc_hcd/imc_hcd.c
@@ -0,0 +1,791 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 "imc_hcd_state.h"
+
+#include <imc/imc_agent.h>
+#include <imc/imc_msg.h>
+#include <imc/imc_os_info.h>
+#include <generic/generic_attr_bool.h>
+#include <generic/generic_attr_chunk.h>
+#include <generic/generic_attr_string.h>
+#include <ietf/ietf_attr.h>
+#include <ietf/ietf_attr_attr_request.h>
+#include "ietf/ietf_attr_fwd_enabled.h"
+#include <pwg/pwg_attr.h>
+#include <pwg/pwg_attr_vendor_smi_code.h>
+
+#include <tncif_pa_subtypes.h>
+
+#include <pen/pen.h>
+#include <utils/debug.h>
+
+/* IMC definitions */
+
+static const char imc_name[] = "HCD";
+
+static pen_type_t msg_types[] = {
+ { PEN_PWG, PA_SUBTYPE_PWG_HCD_SYSTEM },
+ { PEN_PWG, PA_SUBTYPE_PWG_HCD_CONSOLE },
+ { PEN_PWG, PA_SUBTYPE_PWG_HCD_MARKER },
+ { PEN_PWG, PA_SUBTYPE_PWG_HCD_FINISHER },
+ { PEN_PWG, PA_SUBTYPE_PWG_HCD_INTERFACE },
+ { PEN_PWG, PA_SUBTYPE_PWG_HCD_SCANNER }
+};
+
+static imc_agent_t *imc_hcd;
+static imc_os_info_t *os;
+
+typedef struct section_subtype_t section_subtype_t;
+
+struct section_subtype_t {
+ char *section;
+ pa_subtype_pwg_t subtype;
+};
+
+static section_subtype_t section_subtypes[] = {
+ { "system", PA_SUBTYPE_PWG_HCD_SYSTEM },
+ { "console", PA_SUBTYPE_PWG_HCD_CONSOLE },
+ { "marker", PA_SUBTYPE_PWG_HCD_MARKER },
+ { "finisher", PA_SUBTYPE_PWG_HCD_FINISHER },
+ { "interface", PA_SUBTYPE_PWG_HCD_INTERFACE },
+ { "scanner" , PA_SUBTYPE_PWG_HCD_SCANNER }
+};
+
+typedef struct quadruple_t quadruple_t;
+
+struct quadruple_t {
+ char *section;
+ pwg_attr_t name_attr;
+ pwg_attr_t patches_attr;
+ pwg_attr_t string_version_attr;
+ pwg_attr_t version_attr;
+};
+
+static quadruple_t quadruples[] = {
+ { "firmware",
+ PWG_HCD_FIRMWARE_NAME, PWG_HCD_FIRMWARE_PATCHES,
+ PWG_HCD_FIRMWARE_STRING_VERSION, PWG_HCD_FIRMWARE_VERSION },
+ { "resident_application",
+ PWG_HCD_RESIDENT_APP_NAME, PWG_HCD_RESIDENT_APP_PATCHES,
+ PWG_HCD_RESIDENT_APP_STRING_VERSION, PWG_HCD_RESIDENT_APP_VERSION },
+ { "user_application",
+ PWG_HCD_USER_APP_NAME, PWG_HCD_USER_APP_PATCHES,
+ PWG_HCD_USER_APP_STRING_VERSION, PWG_HCD_USER_APP_VERSION }
+};
+
+/**
+ * see section 3.8.1 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_Initialize(TNC_IMCID imc_id,
+ TNC_Version min_version,
+ TNC_Version max_version,
+ TNC_Version *actual_version)
+{
+ if (imc_hcd)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has already been initialized", imc_name);
+ return TNC_RESULT_ALREADY_INITIALIZED;
+ }
+ imc_hcd = imc_agent_create(imc_name, msg_types, countof(msg_types),
+ imc_id, actual_version);
+ if (!imc_hcd)
+ {
+ return TNC_RESULT_FATAL;
+ }
+
+ os = imc_os_info_create();
+ if (!os)
+ {
+ imc_hcd->destroy(imc_hcd);
+ imc_hcd = NULL;
+
+ return TNC_RESULT_FATAL;
+ }
+
+ if (min_version > TNC_IFIMC_VERSION_1 || max_version < TNC_IFIMC_VERSION_1)
+ {
+ DBG1(DBG_IMC, "no common IF-IMC version");
+ return TNC_RESULT_NO_COMMON_VERSION;
+ }
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 3.8.2 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_NotifyConnectionChange(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id, TNC_ConnectionState new_state)
+{
+ imc_state_t *state;
+
+ if (!imc_hcd)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ switch (new_state)
+ {
+ case TNC_CONNECTION_STATE_CREATE:
+ state = imc_hcd_state_create(connection_id);
+ return imc_hcd->create_state(imc_hcd, state);
+ case TNC_CONNECTION_STATE_HANDSHAKE:
+ if (imc_hcd->change_state(imc_hcd, connection_id, new_state,
+ &state) != TNC_RESULT_SUCCESS)
+ {
+ return TNC_RESULT_FATAL;
+ }
+ state->set_result(state, imc_id,
+ TNC_IMV_EVALUATION_RESULT_DONT_KNOW);
+ return TNC_RESULT_SUCCESS;
+ case TNC_CONNECTION_STATE_DELETE:
+ return imc_hcd->delete_state(imc_hcd, connection_id);
+ default:
+ return imc_hcd->change_state(imc_hcd, connection_id,
+ new_state, NULL);
+ }
+}
+
+/**
+ * Add AttributesNaturalLanguage attribute to send queue
+ */
+static void add_attrs_natural_lang(imc_msg_t *msg, char *section)
+{
+ pa_tnc_attr_t *attr;
+ char *string;
+
+ string = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.%s.attributes_natural_language",
+ "en", lib->ns, section);
+ DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_ATTRS_NATURAL_LANG,
+ string);
+ attr = generic_attr_string_create(chunk_from_str(string),
+ pen_type_create(PEN_PWG, PWG_HCD_ATTRS_NATURAL_LANG));
+ msg->add_attribute(msg, attr);
+}
+
+/**
+ * Add DefaultPasswordEnabled attribute to send queue
+ */
+static void add_default_pwd_enabled(imc_msg_t *msg)
+{
+ pa_tnc_attr_t *attr;
+ bool status;
+
+ status = os->get_default_pwd_status(os);
+ DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_DEFAULT_PWD_ENABLED,
+ status ? "yes" : "no");
+ attr = generic_attr_bool_create(status,
+ pen_type_create(PEN_PWG, PWG_HCD_DEFAULT_PWD_ENABLED));
+ msg->add_attribute(msg, attr);
+}
+
+/**
+ * Add ForwardingEnabled attribute to send queue
+ */
+static void add_forwarding_enabled(imc_msg_t *msg)
+{
+ pa_tnc_attr_t *attr;
+ os_fwd_status_t fwd_status;
+
+ fwd_status = os->get_fwd_status(os);
+ DBG2(DBG_IMC, " %N: %N", pwg_attr_names, PWG_HCD_FORWARDING_ENABLED,
+ os_fwd_status_names, fwd_status);
+ attr = ietf_attr_fwd_enabled_create(fwd_status,
+ pen_type_create(PEN_PWG, PWG_HCD_FORWARDING_ENABLED));
+ msg->add_attribute(msg, attr);
+}
+
+/**
+ * Add MachineTypeModel attribute to send queue
+ */
+static void add_machine_type_model(imc_msg_t *msg)
+{
+ pa_tnc_attr_t *attr;
+ char *string;
+
+ string = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.system.machine_type_model",
+ "", lib->ns);
+ DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_MACHINE_TYPE_MODEL,
+ string);
+ attr = generic_attr_string_create(chunk_from_str(string),
+ pen_type_create(PEN_PWG, PWG_HCD_MACHINE_TYPE_MODEL));
+ msg->add_attribute(msg, attr);
+}
+
+/**
+ * Add PSTNFaxEnabled attribute to send queue
+ */
+static void add_pstn_fax_enabled(imc_msg_t *msg)
+{
+ pa_tnc_attr_t *attr;
+ bool status;
+
+ status = lib->settings->get_bool(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.system.pstn_fax_enabled",
+ FALSE, lib->ns);
+ DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_PSTN_FAX_ENABLED,
+ status ? "yes" : "no");
+ attr = generic_attr_bool_create(status,
+ pen_type_create(PEN_PWG, PWG_HCD_PSTN_FAX_ENABLED));
+ msg->add_attribute(msg, attr);
+}
+
+/**
+ * Add TimeSource attribute to send queue
+ */
+static void add_time_source(imc_msg_t *msg)
+{
+ pa_tnc_attr_t *attr;
+ char *string;
+
+ string = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.system.time_source",
+ "", lib->ns);
+ DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_TIME_SOURCE,
+ string);
+ attr = generic_attr_string_create(chunk_from_str(string),
+ pen_type_create(PEN_PWG, PWG_HCD_TIME_SOURCE));
+ msg->add_attribute(msg, attr);
+}
+
+/**
+ * Add UserApplicationEnabled attribute to send queue
+ */
+static void add_user_app_enabled(imc_msg_t *msg)
+{
+ pa_tnc_attr_t *attr;
+ bool status;
+
+ status = lib->settings->get_bool(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.system.user_application_enabled",
+ FALSE, lib->ns);
+ DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_USER_APP_ENABLED,
+ status ? "yes" : "no");
+ attr = generic_attr_bool_create(status,
+ pen_type_create(PEN_PWG, PWG_HCD_USER_APP_ENABLED));
+ msg->add_attribute(msg, attr);
+}
+
+/**
+ * Add UserApplicationPersistenceEnabled attribute to send queue
+ */
+static void add_user_app_persist_enabled(imc_msg_t *msg)
+{
+ pa_tnc_attr_t *attr;
+ bool status;
+
+ status = lib->settings->get_bool(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.system.user_application_persistence.enabled",
+ FALSE, lib->ns);
+ DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_USER_APP_PERSIST_ENABLED,
+ status ? "yes" : "no");
+ attr = generic_attr_bool_create(status,
+ pen_type_create(PEN_PWG, PWG_HCD_USER_APP_PERSIST_ENABLED));
+ msg->add_attribute(msg, attr);
+}
+
+/**
+ * Add VendorName attribute to send queue
+ */
+static void add_vendor_name(imc_msg_t *msg)
+{
+ pa_tnc_attr_t *attr;
+ char *string;
+
+ string = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.system.vendor_name",
+ "", lib->ns);
+ DBG2(DBG_IMC, " %N: %s", pwg_attr_names, PWG_HCD_VENDOR_NAME,
+ string);
+ attr = generic_attr_string_create(chunk_from_str(string),
+ pen_type_create(PEN_PWG, PWG_HCD_VENDOR_NAME));
+ msg->add_attribute(msg, attr);
+}
+
+/**
+ * Add VendorSMICode attribute to send queue
+ */
+static void add_vendor_smi_code(imc_msg_t *msg)
+{
+ pa_tnc_attr_t *attr;
+ int smi_code;
+
+ smi_code = lib->settings->get_int(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.system.vendor_smi_code",
+ 0, lib->ns);
+ DBG2(DBG_IMC, " %N: 0x%06x (%d)", pwg_attr_names, PWG_HCD_VENDOR_SMI_CODE,
+ smi_code, smi_code);
+ attr = pwg_attr_vendor_smi_code_create(smi_code);
+ msg->add_attribute(msg, attr);
+}
+
+/**
+ * Add CertificationState attribute to send queue
+ */
+static void add_certification_state(imc_msg_t *msg)
+{
+ pa_tnc_attr_t *attr;
+ char *hex_string;
+ chunk_t blob;
+
+ hex_string = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.system.certification_state",
+ NULL, lib->ns);
+ if (hex_string)
+ {
+ blob = chunk_from_hex(chunk_from_str(hex_string), NULL);
+
+ DBG2(DBG_IMC, " %N: %B", pwg_attr_names, PWG_HCD_CERTIFICATION_STATE,
+ &blob);
+ attr = generic_attr_chunk_create(blob,
+ pen_type_create(PEN_PWG, PWG_HCD_CERTIFICATION_STATE));
+ msg->add_attribute(msg, attr);
+ chunk_free(&blob);
+ }
+}
+
+/**
+ * Add CertificationState attribute to send queue
+ */
+static void add_configuration_state(imc_msg_t *msg)
+{
+ pa_tnc_attr_t *attr;
+ char *hex_string;
+ chunk_t blob;
+
+ hex_string = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.system.configuration_state",
+ NULL, lib->ns);
+ if (hex_string)
+ {
+ blob = chunk_from_hex(chunk_from_str(hex_string), NULL);
+
+ DBG2(DBG_IMC, " %N: %B", pwg_attr_names, PWG_HCD_CONFIGURATION_STATE,
+ &blob);
+ attr = generic_attr_chunk_create(blob,
+ pen_type_create(PEN_PWG, PWG_HCD_CONFIGURATION_STATE));
+ msg->add_attribute(msg, attr);
+ chunk_free(&blob);
+ }
+}
+
+/**
+ * Add Correlated Attributes to send queue
+ */
+static void add_quadruple(imc_msg_t *msg, char *section, quadruple_t *quad)
+{
+ pa_tnc_attr_t *attr;
+ const size_t version_len = 16;
+ char version[version_len];
+ char hex_version_default[] = "00000000000000000000000000000000";
+ char *app, *name, *patches, *string_version, *hex_version;
+ size_t len;
+ chunk_t num_version;
+ enumerator_t *enumerator;
+
+ enumerator = lib->settings->create_section_enumerator(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.%s.%s",
+ lib->ns, section, quad->section);
+ while (enumerator->enumerate(enumerator, &app))
+ {
+ name = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.%s.%s.%s.name",
+ "", lib->ns, section, quad->section, app);
+ patches = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.%s.%s.%s.patches",
+ "", lib->ns, section, quad->section, app);
+ string_version = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.%s.%s.%s.string_version",
+ "", lib->ns, section, quad->section, app);
+ hex_version = lib->settings->get_str(lib->settings,
+ "%s.plugins.imc-hcd.subtypes.%s.%s.%s.version",
+ hex_version_default, lib->ns, section, quad->section, app);
+
+ /* convert hex string into binary chunk */
+ if (strlen(hex_version) > 2 * version_len)
+ {
+ hex_version = hex_version_default;
+ }
+ num_version = chunk_from_hex(chunk_from_str(hex_version), version);
+
+ DBG2(DBG_IMC, "--- %s ---", app);
+
+ DBG2(DBG_IMC, " %N: %s", pwg_attr_names, quad->name_attr, name);
+ attr = generic_attr_string_create(chunk_from_str(name),
+ pen_type_create(PEN_PWG, quad->name_attr));
+ msg->add_attribute(msg, attr);
+
+ /* remove any trailing LF from patches string for logging */
+ len = strlen(patches);
+ if (len && (patches[len - 1] == '\n'))
+ {
+ len--;
+ }
+ DBG2(DBG_IMC, " %N:%s%.*s", pwg_attr_names, quad->patches_attr,
+ len ? "\n" : " ", len, patches);
+ attr = generic_attr_string_create(chunk_from_str(patches),
+ pen_type_create(PEN_PWG, quad->patches_attr));
+ msg->add_attribute(msg, attr);
+
+ DBG2(DBG_IMC, " %N: %s", pwg_attr_names, quad->string_version_attr,
+ string_version);
+ attr = generic_attr_string_create(chunk_from_str(string_version),
+ pen_type_create(PEN_PWG, quad->string_version_attr));
+ msg->add_attribute(msg, attr);
+
+ DBG2(DBG_IMC, " %N: %#B", pwg_attr_names, quad->version_attr, &num_version);
+ attr = generic_attr_chunk_create(num_version,
+ pen_type_create(PEN_PWG, quad->version_attr));
+ msg->add_attribute(msg, attr);
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * see section 3.8.3 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id)
+{
+ imc_state_t *state;
+ imc_msg_t *out_msg;
+ TNC_Result result = TNC_RESULT_SUCCESS;
+ pa_subtype_pwg_t subtype;
+ pen_type_t msg_type;
+ enumerator_t *enumerator;
+ char *section;
+ int i;
+
+ if (!imc_hcd)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ if (!imc_hcd->get_state(imc_hcd, connection_id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+
+ /* Enumerate over all HCD subtype sections */
+ enumerator = lib->settings->create_section_enumerator(lib->settings,
+ "%s.plugins.imc-hcd.subtypes", lib->ns);
+ while (enumerator->enumerate(enumerator, &section) &&
+ result == TNC_RESULT_SUCCESS)
+ {
+ subtype = PA_SUBTYPE_PWG_HCD_UNKNOWN;
+
+ for (i = 0; i < countof(section_subtypes); i++)
+ {
+ if (streq(section, section_subtypes[i].section))
+ {
+ subtype = section_subtypes[i].subtype;
+ break;
+ }
+ }
+ if (subtype == PA_SUBTYPE_PWG_HCD_UNKNOWN)
+ {
+ DBG1(DBG_IMC, "HCD subtype '%s' not supported", section);
+ continue;
+ }
+ DBG2(DBG_IMC, "retrieving attributes for PA subtype %N/%N",
+ pen_names, PEN_PWG, pa_subtype_pwg_names, subtype);
+
+ msg_type = pen_type_create(PEN_PWG, subtype);
+ out_msg = imc_msg_create(imc_hcd, state, connection_id, imc_id,
+ TNC_IMVID_ANY, msg_type);
+
+ /* mandatory attributes that are always sent without request */
+ add_attrs_natural_lang(out_msg, section);
+ if (subtype == PA_SUBTYPE_PWG_HCD_SYSTEM)
+ {
+ add_default_pwd_enabled(out_msg);
+ add_forwarding_enabled(out_msg);
+ add_machine_type_model(out_msg);
+ add_pstn_fax_enabled(out_msg);
+ add_time_source(out_msg);
+ add_vendor_name(out_msg);
+ add_vendor_smi_code(out_msg);
+ add_user_app_enabled(out_msg);
+ add_user_app_persist_enabled(out_msg);
+ }
+ if (lib->settings->get_bool(lib->settings,
+ "%s.plugins.imc-hcd.push_info", FALSE, lib->ns))
+ {
+ /* correlated attributes */
+ for (i = 0; i < countof(quadruples); i++)
+ {
+ add_quadruple(out_msg, section, &quadruples[i]);
+ }
+ }
+
+ /* send PA-TNC message with the excl flag not set */
+ result = out_msg->send(out_msg, FALSE);
+ out_msg->destroy(out_msg);
+ }
+ enumerator->destroy(enumerator);
+
+ return result;
+}
+
+static TNC_Result receive_message(imc_state_t *state, imc_msg_t *in_msg)
+{
+ imc_msg_t *out_msg;
+ enumerator_t *enumerator;
+ pa_tnc_attr_t *attr;
+ pen_type_t type, msg_type;
+ TNC_Result result;
+ char *section = NULL;
+ int i;
+ bool fatal_error = FALSE, pushed_info;
+
+ /* generate an outgoing PA-TNC message - we might need it */
+ out_msg = imc_msg_create_as_reply(in_msg);
+
+ /* parse received PA-TNC message and handle local and remote errors */
+ result = in_msg->receive(in_msg, out_msg, &fatal_error);
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ out_msg->destroy(out_msg);
+ return result;
+ }
+ msg_type = in_msg->get_msg_type(in_msg);
+
+ for (i = 0; i < countof(section_subtypes); i++)
+ {
+ if (msg_type.type == section_subtypes[i].subtype)
+ {
+ section = section_subtypes[i].section;
+ break;
+ }
+ }
+ pushed_info = lib->settings->get_bool(lib->settings,
+ "%s.plugins.imc-hcd.push_info", FALSE, lib->ns);
+
+ /* analyze PA-TNC attributes */
+ enumerator = in_msg->create_attribute_enumerator(in_msg);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ type = attr->get_type(attr);
+
+ if (type.vendor_id == PEN_IETF)
+ {
+ if (type.type == IETF_ATTR_ATTRIBUTE_REQUEST)
+ {
+ ietf_attr_attr_request_t *attr_cast;
+ pen_type_t *entry;
+ enumerator_t *e;
+
+ attr_cast = (ietf_attr_attr_request_t*)attr;
+
+ e = attr_cast->create_enumerator(attr_cast);
+ while (e->enumerate(e, &entry))
+ {
+ if (entry->vendor_id == PEN_PWG)
+ {
+ switch (entry->type)
+ {
+ case PWG_HCD_ATTRS_NATURAL_LANG:
+ add_attrs_natural_lang(out_msg, section);
+ break;
+ case PWG_HCD_DEFAULT_PWD_ENABLED:
+ add_default_pwd_enabled(out_msg);
+ break;
+ case PWG_HCD_FORWARDING_ENABLED:
+ add_forwarding_enabled(out_msg);
+ break;
+ case PWG_HCD_MACHINE_TYPE_MODEL:
+ add_machine_type_model(out_msg);
+ break;
+ case PWG_HCD_PSTN_FAX_ENABLED:
+ add_pstn_fax_enabled(out_msg);
+ break;
+ case PWG_HCD_TIME_SOURCE:
+ add_time_source(out_msg);
+ break;
+ case PWG_HCD_USER_APP_ENABLED:
+ add_user_app_enabled(out_msg);
+ break;
+ case PWG_HCD_USER_APP_PERSIST_ENABLED:
+ add_user_app_persist_enabled(out_msg);
+ break;
+ case PWG_HCD_VENDOR_NAME:
+ add_vendor_name(out_msg);
+ break;
+ case PWG_HCD_VENDOR_SMI_CODE:
+ add_vendor_smi_code(out_msg);
+ break;
+ case PWG_HCD_CERTIFICATION_STATE:
+ add_certification_state(out_msg);
+ break;
+ case PWG_HCD_CONFIGURATION_STATE:
+ add_configuration_state(out_msg);
+ break;
+ default:
+ if (pushed_info)
+ {
+ continue;
+ }
+ }
+
+ /* if not pushed, deliver on request */
+ switch (entry->type)
+ {
+ case PWG_HCD_FIRMWARE_NAME:
+ add_quadruple(out_msg, section, &quadruples[0]);
+ break;
+ case PWG_HCD_RESIDENT_APP_NAME:
+ add_quadruple(out_msg, section, &quadruples[1]);
+ break;
+ case PWG_HCD_USER_APP_NAME:
+ add_quadruple(out_msg, section, &quadruples[2]);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ e->destroy(e);
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (fatal_error)
+ {
+ result = TNC_RESULT_FATAL;
+ }
+ else
+ {
+ /* send PA-TNC message with the EXCL flag set */
+ result = out_msg->send(out_msg, TRUE);
+ }
+ out_msg->destroy(out_msg);
+
+ return result;
+}
+
+/**
+ * see section 3.8.4 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_ReceiveMessage(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_MessageType msg_type)
+{
+ imc_state_t *state;
+ imc_msg_t *in_msg;
+ TNC_Result result;
+
+ if (!imc_hcd)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ if (!imc_hcd->get_state(imc_hcd, connection_id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ in_msg = imc_msg_create_from_data(imc_hcd, state, connection_id, msg_type,
+ chunk_create(msg, msg_len));
+ result = receive_message(state, in_msg);
+ in_msg->destroy(in_msg);
+
+ return result;
+}
+
+/**
+ * see section 3.8.6 of TCG TNC IF-IMV Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_ReceiveMessageLong(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id,
+ TNC_UInt32 msg_flags,
+ TNC_BufferReference msg,
+ TNC_UInt32 msg_len,
+ TNC_VendorID msg_vid,
+ TNC_MessageSubtype msg_subtype,
+ TNC_UInt32 src_imv_id,
+ TNC_UInt32 dst_imc_id)
+{
+ imc_state_t *state;
+ imc_msg_t *in_msg;
+ TNC_Result result;
+
+ if (!imc_hcd)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ if (!imc_hcd->get_state(imc_hcd, connection_id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ in_msg = imc_msg_create_from_long_data(imc_hcd, state, connection_id,
+ src_imv_id, dst_imc_id,msg_vid, msg_subtype,
+ chunk_create(msg, msg_len));
+ result =receive_message(state, in_msg);
+ in_msg->destroy(in_msg);
+
+ return result;
+}
+
+/**
+ * see section 3.8.7 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_BatchEnding(TNC_IMCID imc_id,
+ TNC_ConnectionID connection_id)
+{
+ if (!imc_hcd)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 3.8.8 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_Terminate(TNC_IMCID imc_id)
+{
+ if (!imc_hcd)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ imc_hcd->destroy(imc_hcd);
+ imc_hcd = NULL;
+
+ os->destroy(os);
+ os = NULL;
+
+ return TNC_RESULT_SUCCESS;
+}
+
+/**
+ * see section 4.2.8.1 of TCG TNC IF-IMC Specification 1.3
+ */
+TNC_Result TNC_IMC_API TNC_IMC_ProvideBindFunction(TNC_IMCID imc_id,
+ TNC_TNCC_BindFunctionPointer bind_function)
+{
+ if (!imc_hcd)
+ {
+ DBG1(DBG_IMC, "IMC \"%s\" has not been initialized", imc_name);
+ return TNC_RESULT_NOT_INITIALIZED;
+ }
+ return imc_hcd->bind_functions(imc_hcd, bind_function);
+}
diff --git a/src/libimcv/plugins/imc_hcd/imc_hcd_state.c b/src/libimcv/plugins/imc_hcd/imc_hcd_state.c
new file mode 100644
index 000000000..ce93d7ef7
--- /dev/null
+++ b/src/libimcv/plugins/imc_hcd/imc_hcd_state.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 "imc_hcd_state.h"
+
+#include <tncif_names.h>
+
+#include <utils/debug.h>
+
+typedef struct private_imc_hcd_state_t private_imc_hcd_state_t;
+
+/**
+ * Private data of an imc_hcd_state_t object.
+ */
+struct private_imc_hcd_state_t {
+
+ /**
+ * Public members of imc_hcd_state_t
+ */
+ imc_hcd_state_t public;
+
+ /**
+ * TNCCS connection ID
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * TNCCS connection state
+ */
+ TNC_ConnectionState state;
+
+ /**
+ * Assessment/Evaluation Result
+ */
+ TNC_IMV_Evaluation_Result result;
+
+ /**
+ * Does the TNCCS connection support long message types?
+ */
+ bool has_long;
+
+ /**
+ * Does the TNCCS connection support exclusive delivery?
+ */
+ bool has_excl;
+
+ /**
+ * Maximum PA-TNC message size for this TNCCS connection
+ */
+ u_int32_t max_msg_len;
+
+ /**
+ * PA-TNC attribute segmentation contracts associated with TNCCS connection
+ */
+ seg_contract_manager_t *contracts;
+};
+
+METHOD(imc_state_t, get_connection_id, TNC_ConnectionID,
+ private_imc_hcd_state_t *this)
+{
+ return this->connection_id;
+}
+
+METHOD(imc_state_t, has_long, bool,
+ private_imc_hcd_state_t *this)
+{
+ return this->has_long;
+}
+
+METHOD(imc_state_t, has_excl, bool,
+ private_imc_hcd_state_t *this)
+{
+ return this->has_excl;
+}
+
+METHOD(imc_state_t, set_flags, void,
+ private_imc_hcd_state_t *this, bool has_long, bool has_excl)
+{
+ this->has_long = has_long;
+ this->has_excl = has_excl;
+}
+
+METHOD(imc_state_t, set_max_msg_len, void,
+ private_imc_hcd_state_t *this, u_int32_t max_msg_len)
+{
+ this->max_msg_len = max_msg_len;
+}
+
+METHOD(imc_state_t, get_max_msg_len, u_int32_t,
+ private_imc_hcd_state_t *this)
+{
+ return this->max_msg_len;
+}
+
+METHOD(imc_state_t, get_contracts, seg_contract_manager_t*,
+ private_imc_hcd_state_t *this)
+{
+ return this->contracts;
+}
+
+METHOD(imc_state_t, change_state, void,
+ private_imc_hcd_state_t *this, TNC_ConnectionState new_state)
+{
+ this->state = new_state;
+}
+
+METHOD(imc_state_t, set_result, void,
+ private_imc_hcd_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result result)
+{
+ this->result = result;
+}
+
+METHOD(imc_state_t, get_result, bool,
+ private_imc_hcd_state_t *this, TNC_IMCID id,
+ TNC_IMV_Evaluation_Result *result)
+{
+ if (result)
+ {
+ *result = this->result;
+ }
+ return this->result != TNC_IMV_EVALUATION_RESULT_DONT_KNOW;
+}
+
+METHOD(imc_state_t, destroy, void,
+ private_imc_hcd_state_t *this)
+{
+ this->contracts->destroy(this->contracts);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+imc_state_t *imc_hcd_state_create(TNC_ConnectionID connection_id)
+{
+ private_imc_hcd_state_t *this;
+
+ INIT(this,
+ .public = {
+ .interface = {
+ .get_connection_id = _get_connection_id,
+ .has_long = _has_long,
+ .has_excl = _has_excl,
+ .set_flags = _set_flags,
+ .set_max_msg_len = _set_max_msg_len,
+ .get_max_msg_len = _get_max_msg_len,
+ .get_contracts = _get_contracts,
+ .change_state = _change_state,
+ .set_result = _set_result,
+ .get_result = _get_result,
+ .destroy = _destroy,
+ },
+ },
+ .state = TNC_CONNECTION_STATE_CREATE,
+ .result = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
+ .connection_id = connection_id,
+ .contracts = seg_contract_manager_create(),
+ );
+
+ return &this->public.interface;
+}
+
+
diff --git a/src/libimcv/plugins/imc_hcd/imc_hcd_state.h b/src/libimcv/plugins/imc_hcd/imc_hcd_state.h
new file mode 100644
index 000000000..dbd5ddb4f
--- /dev/null
+++ b/src/libimcv/plugins/imc_hcd/imc_hcd_state.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 imc_hcd imc_hcd
+ * @ingroup libimcv_plugins
+ *
+ * @defgroup imc_hcd_state_t imc_hcd_state
+ * @{ @ingroup imc_hcd
+ */
+
+#ifndef IMC_HCD_STATE_H_
+#define IMC_HCD_STATE_H_
+
+#include <imc/imc_state.h>
+#include <library.h>
+
+typedef struct imc_hcd_state_t imc_hcd_state_t;
+
+/**
+ * Internal state of an imc_hcd_t connection instance
+ */
+struct imc_hcd_state_t {
+
+ /**
+ * imc_state_t interface
+ */
+ imc_state_t interface;
+};
+
+/**
+ * Create an imc_hcd_state_t instance
+ *
+ * @param id connection ID
+ */
+imc_state_t* imc_hcd_state_create(TNC_ConnectionID id);
+
+#endif /** IMC_HCD_STATE_H_ @}*/
diff --git a/src/libimcv/plugins/imc_os/imc_os.c b/src/libimcv/plugins/imc_os/imc_os.c
index 4fe8856e6..af1862ad3 100644
--- a/src/libimcv/plugins/imc_os/imc_os.c
+++ b/src/libimcv/plugins/imc_os/imc_os.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2014 Andreas Steffen
+ * Copyright (C) 2011-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -18,10 +18,11 @@
#include <imc/imc_agent.h>
#include <imc/imc_msg.h>
#include <imc/imc_os_info.h>
+#include <generic/generic_attr_bool.h>
+#include <generic/generic_attr_string.h>
#include <ietf/ietf_attr.h>
#include <ietf/ietf_attr_attr_request.h>
-#include <ietf/ietf_attr_default_pwd_enabled.h>
-#include <ietf/ietf_attr_fwd_enabled.h>
+#include "ietf/ietf_attr_fwd_enabled.h"
#include <ietf/ietf_attr_installed_packages.h>
#include <ietf/ietf_attr_numeric_version.h>
#include <ietf/ietf_attr_op_status.h>
@@ -30,7 +31,6 @@
#include <ita/ita_attr.h>
#include <ita/ita_attr_get_settings.h>
#include <ita/ita_attr_settings.h>
-#include <ita/ita_attr_device_id.h>
#include <tncif_pa_subtypes.h>
@@ -212,9 +212,9 @@ static void add_fwd_enabled(imc_msg_t *msg)
os_fwd_status_t fwd_status;
fwd_status = os->get_fwd_status(os);
- DBG1(DBG_IMC, "IPv4 forwarding is %N",
- os_fwd_status_names, fwd_status);
- attr = ietf_attr_fwd_enabled_create(fwd_status);
+ DBG1(DBG_IMC, "IPv4 forwarding is %N", os_fwd_status_names, fwd_status);
+ attr = ietf_attr_fwd_enabled_create(fwd_status,
+ pen_type_create(PEN_IETF, IETF_ATTR_FORWARDING_ENABLED));
msg->add_attribute(msg, attr);
}
@@ -224,9 +224,12 @@ static void add_fwd_enabled(imc_msg_t *msg)
static void add_default_pwd_enabled(imc_msg_t *msg)
{
pa_tnc_attr_t *attr;
+ bool status;
- DBG1(DBG_IMC, "factory default password is disabled");
- attr = ietf_attr_default_pwd_enabled_create(FALSE);
+ status = os->get_default_pwd_status(os);
+ DBG1(DBG_IMC, "factory default password is %sabled", status ? "en" : "dis");
+ attr = generic_attr_bool_create(status,
+ pen_type_create(PEN_IETF, IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED));
msg->add_attribute(msg, attr);
}
@@ -330,7 +333,8 @@ static void add_device_id(imc_msg_t *msg)
}
DBG1(DBG_IMC, "device ID is %.*s", value.len, value.ptr);
- attr = ita_attr_device_id_create(value);
+ attr = generic_attr_string_create(value, pen_type_create(PEN_ITA,
+ ITA_ATTR_DEVICE_ID));
msg->add_attribute(msg, attr);
free(value.ptr);
}
diff --git a/src/libimcv/plugins/imc_scanner/imc_scanner.c b/src/libimcv/plugins/imc_scanner/imc_scanner.c
index 0478841cb..c67636f8f 100644
--- a/src/libimcv/plugins/imc_scanner/imc_scanner.c
+++ b/src/libimcv/plugins/imc_scanner/imc_scanner.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2014 Andreas Steffen
+ * Copyright (C) 2011-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -34,7 +34,7 @@
static const char imc_name[] = "Scanner";
static pen_type_t msg_types[] = {
- { PEN_IETF, PA_SUBTYPE_IETF_VPN }
+ { PEN_IETF, PA_SUBTYPE_IETF_FIREWALL }
};
static imc_agent_t *imc_scanner;
@@ -241,7 +241,8 @@ static TNC_Result add_port_filter(imc_msg_t *msg)
pa_tnc_attr_t *attr;
ietf_attr_port_filter_t *attr_port_filter;
- attr = ietf_attr_port_filter_create();
+ attr = ietf_attr_port_filter_create(pen_type_create(PEN_IETF,
+ IETF_ATTR_PORT_FILTER));
attr->set_noskip_flag(attr, TRUE);
attr_port_filter = (ietf_attr_port_filter_t*)attr;
if (!do_netstat(attr_port_filter))
diff --git a/src/libimcv/plugins/imc_swid/imc_swid.c b/src/libimcv/plugins/imc_swid/imc_swid.c
index 40f352ad9..0dcb9afb6 100644
--- a/src/libimcv/plugins/imc_swid/imc_swid.c
+++ b/src/libimcv/plugins/imc_swid/imc_swid.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 Andreas Steffen
+ * Copyright (C) 2013-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -134,9 +134,7 @@ TNC_Result TNC_IMC_BeginHandshake(TNC_IMCID imc_id,
/* Determine maximum PA-TNC attribute segment size */
max_seg_size = state->get_max_msg_len(state) - PA_TNC_HEADER_SIZE
- PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_SEG_ENV_HEADER
- - PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+ - TCG_SEG_ATTR_SEG_ENV_HEADER;
/* Announce support of PA-TNC segmentation to IMV */
contract = seg_contract_create(msg_types[0], max_attr_size, max_seg_size,
diff --git a/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c b/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c
index 8e3736857..28ebd0069 100644
--- a/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c
+++ b/src/libimcv/plugins/imv_attestation/imv_attestation_agent.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2011-2012 Sansar Choinyambuu
- * Copyright (C) 2011-2014 Andreas Steffen
+ * Copyright (C) 2011-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -27,13 +27,13 @@
#include <imv/imv_msg.h>
#include <imv/imv_session.h>
#include <imv/imv_os_info.h>
+#include <generic/generic_attr_string.h>
#include <ietf/ietf_attr.h>
#include <ietf/ietf_attr_attr_request.h>
#include <ietf/ietf_attr_pa_tnc_error.h>
#include <ietf/ietf_attr_product_info.h>
#include <ietf/ietf_attr_string_version.h>
#include <ita/ita_attr.h>
-#include <ita/ita_attr_device_id.h>
#include <tcg/tcg_attr.h>
#include <tcg/pts/tcg_pts_attr_meas_algo.h>
#include <tcg/pts/tcg_pts_attr_proto_caps.h>
@@ -484,9 +484,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
max_seg_size = state->get_max_msg_len(state)
- PA_TNC_HEADER_SIZE
- PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_SEG_ENV_HEADER
- - PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+ - TCG_SEG_ATTR_SEG_ENV_HEADER;
/* Announce support of PA-TNC segmentation to IMC */
contract = seg_contract_create(msg_types[0], max_attr_size,
diff --git a/src/libimcv/plugins/imv_hcd/Makefile.am b/src/libimcv/plugins/imv_hcd/Makefile.am
new file mode 100644
index 000000000..28926d45e
--- /dev/null
+++ b/src/libimcv/plugins/imv_hcd/Makefile.am
@@ -0,0 +1,18 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libimcv
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+imcv_LTLIBRARIES = imv-hcd.la
+
+imv_hcd_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+imv_hcd_la_SOURCES = \
+ imv_hcd.c imv_hcd_state.h imv_hcd_state.c \
+ imv_hcd_agent.h imv_hcd_agent.c
+
+imv_hcd_la_LDFLAGS = -module -avoid-version -no-undefined
diff --git a/src/libimcv/plugins/imv_hcd/Makefile.in b/src/libimcv/plugins/imv_hcd/Makefile.in
new file mode 100644
index 000000000..ea017646d
--- /dev/null
+++ b/src/libimcv/plugins/imv_hcd/Makefile.in
@@ -0,0 +1,767 @@
+# 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/libimcv/plugins/imv_hcd
+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)$(imcvdir)"
+LTLIBRARIES = $(imcv_LTLIBRARIES)
+imv_hcd_la_DEPENDENCIES = $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+am_imv_hcd_la_OBJECTS = imv_hcd.lo imv_hcd_state.lo imv_hcd_agent.lo
+imv_hcd_la_OBJECTS = $(am_imv_hcd_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 =
+imv_hcd_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(imv_hcd_la_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(imv_hcd_la_SOURCES)
+DIST_SOURCES = $(imv_hcd_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libtncif \
+ -I$(top_srcdir)/src/libimcv
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+imcv_LTLIBRARIES = imv-hcd.la
+imv_hcd_la_LIBADD = $(top_builddir)/src/libimcv/libimcv.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la
+
+imv_hcd_la_SOURCES = \
+ imv_hcd.c imv_hcd_state.h imv_hcd_state.c \
+ imv_hcd_agent.h imv_hcd_agent.c
+
+imv_hcd_la_LDFLAGS = -module -avoid-version -no-undefined
+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/libimcv/plugins/imv_hcd/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libimcv/plugins/imv_hcd/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):
+
+install-imcvLTLIBRARIES: $(imcv_LTLIBRARIES)
+ @$(NORMAL_INSTALL)
+ @list='$(imcv_LTLIBRARIES)'; test -n "$(imcvdir)" || 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)$(imcvdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(imcvdir)" || exit 1; \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(imcvdir)'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(imcvdir)"; \
+ }
+
+uninstall-imcvLTLIBRARIES:
+ @$(NORMAL_UNINSTALL)
+ @list='$(imcv_LTLIBRARIES)'; test -n "$(imcvdir)" || list=; \
+ for p in $$list; do \
+ $(am__strip_dir) \
+ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(imcvdir)/$$f'"; \
+ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(imcvdir)/$$f"; \
+ done
+
+clean-imcvLTLIBRARIES:
+ -test -z "$(imcv_LTLIBRARIES)" || rm -f $(imcv_LTLIBRARIES)
+ @list='$(imcv_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}; \
+ }
+
+imv-hcd.la: $(imv_hcd_la_OBJECTS) $(imv_hcd_la_DEPENDENCIES) $(EXTRA_imv_hcd_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(imv_hcd_la_LINK) -rpath $(imcvdir) $(imv_hcd_la_OBJECTS) $(imv_hcd_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_hcd.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_hcd_agent.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/imv_hcd_state.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)$(imcvdir)"; 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-imcvLTLIBRARIES clean-libtool \
+ 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-imcvLTLIBRARIES
+
+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-imcvLTLIBRARIES
+
+.MAKE: install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
+ clean-imcvLTLIBRARIES clean-libtool cscopelist-am ctags \
+ ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am \
+ install-imcvLTLIBRARIES install-info install-info-am \
+ install-man install-pdf install-pdf-am install-ps \
+ install-ps-am install-strip installcheck installcheck-am \
+ installdirs maintainer-clean maintainer-clean-generic \
+ mostlyclean mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool pdf pdf-am ps ps-am tags tags-am uninstall \
+ uninstall-am uninstall-imcvLTLIBRARIES
+
+
+# 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/libimcv/plugins/imv_hcd/imv_hcd.c b/src/libimcv/plugins/imv_hcd/imv_hcd.c
new file mode 100644
index 000000000..f32095217
--- /dev/null
+++ b/src/libimcv/plugins/imv_hcd/imv_hcd.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 "imv_hcd_agent.h"
+
+static const char imv_name[] = "HCD";
+static const imv_agent_create_t imv_agent_create = imv_hcd_agent_create;
+
+/* include generic TGC TNC IF-IMV API code below */
+
+#include <imv/imv_if.h>
+
diff --git a/src/libimcv/plugins/imv_hcd/imv_hcd_agent.c b/src/libimcv/plugins/imv_hcd/imv_hcd_agent.c
new file mode 100644
index 000000000..e15eeb10a
--- /dev/null
+++ b/src/libimcv/plugins/imv_hcd/imv_hcd_agent.c
@@ -0,0 +1,680 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+
+#include "imv_hcd_agent.h"
+#include "imv_hcd_state.h"
+
+#include <imcv.h>
+#include <imv/imv_agent.h>
+#include <imv/imv_msg.h>
+#include <generic/generic_attr_bool.h>
+#include <generic/generic_attr_chunk.h>
+#include <generic/generic_attr_string.h>
+#include <ietf/ietf_attr.h>
+#include <ietf/ietf_attr_attr_request.h>
+#include <ietf/ietf_attr_fwd_enabled.h>
+#include <pwg/pwg_attr.h>
+#include <pwg/pwg_attr_vendor_smi_code.h>
+#include "tcg/seg/tcg_seg_attr_max_size.h"
+#include "tcg/seg/tcg_seg_attr_seg_env.h"
+
+#include <tncif_names.h>
+#include <tncif_pa_subtypes.h>
+
+#include <pen/pen.h>
+#include <utils/debug.h>
+
+#define HCD_MAX_ATTR_SIZE 10000000
+
+typedef struct private_imv_hcd_agent_t private_imv_hcd_agent_t;
+
+/* Subscribed PA-TNC message subtypes */
+static pen_type_t msg_types[] = {
+ { PEN_IETF, PA_SUBTYPE_IETF_OPERATING_SYSTEM },
+ { PEN_PWG, PA_SUBTYPE_PWG_HCD_SYSTEM },
+ { PEN_PWG, PA_SUBTYPE_PWG_HCD_CONSOLE },
+ { PEN_PWG, PA_SUBTYPE_PWG_HCD_MARKER },
+ { PEN_PWG, PA_SUBTYPE_PWG_HCD_FINISHER },
+ { PEN_PWG, PA_SUBTYPE_PWG_HCD_INTERFACE },
+ { PEN_PWG, PA_SUBTYPE_PWG_HCD_SCANNER }
+};
+
+static imv_hcd_attr_t attr_type_to_flag(pwg_attr_t attr_type)
+{
+ switch (attr_type)
+ {
+ case PWG_HCD_DEFAULT_PWD_ENABLED:
+ return IMV_HCD_ATTR_DEFAULT_PWD_ENABLED;
+ case PWG_HCD_FIREWALL_SETTING:
+ return IMV_HCD_ATTR_FIREWALL_SETTING;
+ case PWG_HCD_FORWARDING_ENABLED:
+ return IMV_HCD_ATTR_FORWARDING_ENABLED;
+ case PWG_HCD_MACHINE_TYPE_MODEL:
+ return IMV_HCD_ATTR_MACHINE_TYPE_MODEL;
+ case PWG_HCD_PSTN_FAX_ENABLED:
+ return IMV_HCD_ATTR_PSTN_FAX_ENABLED;
+ case PWG_HCD_TIME_SOURCE:
+ return IMV_HCD_ATTR_TIME_SOURCE;
+ case PWG_HCD_USER_APP_ENABLED:
+ return IMV_HCD_ATTR_USER_APP_ENABLED;
+ case PWG_HCD_USER_APP_PERSIST_ENABLED:
+ return IMV_HCD_ATTR_USER_APP_PERSIST_ENABLED;
+ case PWG_HCD_VENDOR_NAME:
+ return IMV_HCD_ATTR_VENDOR_NAME;
+ case PWG_HCD_VENDOR_SMI_CODE:
+ return IMV_HCD_ATTR_VENDOR_SMI_CODE;
+ case PWG_HCD_CERTIFICATION_STATE:
+ return IMV_HCD_ATTR_CERTIFICATION_STATE;
+ case PWG_HCD_CONFIGURATION_STATE:
+ return IMV_HCD_ATTR_CONFIGURATION_STATE;
+ case PWG_HCD_ATTRS_NATURAL_LANG:
+ return IMV_HCD_ATTR_NATURAL_LANG;
+ case PWG_HCD_FIRMWARE_NAME:
+ return IMV_HCD_ATTR_FIRMWARE_NAME;
+ case PWG_HCD_RESIDENT_APP_NAME:
+ return IMV_HCD_ATTR_RESIDENT_APP_NAME;
+ case PWG_HCD_USER_APP_NAME:
+ return IMV_HCD_ATTR_USER_APP_NAME;
+ default:
+ return IMV_HCD_ATTR_NONE;
+ }
+}
+
+/**
+ * Private data of an imv_hcd_agent_t object.
+ */
+struct private_imv_hcd_agent_t {
+
+ /**
+ * Public members of imv_hcd_agent_t
+ */
+ imv_agent_if_t public;
+
+ /**
+ * IMV agent responsible for generic functions
+ */
+ imv_agent_t *agent;
+
+};
+
+METHOD(imv_agent_if_t, bind_functions, TNC_Result,
+ private_imv_hcd_agent_t *this, TNC_TNCS_BindFunctionPointer bind_function)
+{
+ return this->agent->bind_functions(this->agent, bind_function);
+}
+
+METHOD(imv_agent_if_t, notify_connection_change, TNC_Result,
+ private_imv_hcd_agent_t *this, TNC_ConnectionID id,
+ TNC_ConnectionState new_state)
+{
+ TNC_IMV_Action_Recommendation rec;
+ imv_state_t *state;
+ imv_session_t *session;
+
+ switch (new_state)
+ {
+ case TNC_CONNECTION_STATE_CREATE:
+ state = imv_hcd_state_create(id);
+ return this->agent->create_state(this->agent, state);
+ case TNC_CONNECTION_STATE_DELETE:
+ return this->agent->delete_state(this->agent, id);
+ case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
+ case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
+ case TNC_CONNECTION_STATE_ACCESS_NONE:
+ if (this->agent->get_state(this->agent, id, &state) && imcv_db)
+ {
+ session = state->get_session(state);
+
+ if (session->get_policy_started(session))
+ {
+ switch (new_state)
+ {
+ case TNC_CONNECTION_STATE_ACCESS_ALLOWED:
+ rec = TNC_IMV_ACTION_RECOMMENDATION_ALLOW;
+ break;
+ case TNC_CONNECTION_STATE_ACCESS_ISOLATED:
+ rec = TNC_IMV_ACTION_RECOMMENDATION_ISOLATE;
+ break;
+ case TNC_CONNECTION_STATE_ACCESS_NONE:
+ default:
+ rec = TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS;
+ }
+ imcv_db->add_recommendation(imcv_db, session, rec);
+ if (!imcv_db->policy_script(imcv_db, session, FALSE))
+ {
+ DBG1(DBG_IMV, "error in policy script stop");
+ }
+ }
+ }
+ /* fall through to default state */
+ default:
+ return this->agent->change_state(this->agent, id, new_state, NULL);
+ }
+}
+
+/**
+ * Process a received message
+ */
+static TNC_Result receive_msg(private_imv_hcd_agent_t *this, imv_state_t *state,
+ imv_msg_t *in_msg)
+{
+ imv_msg_t *out_msg;
+ imv_hcd_state_t *hcd_state;
+ pa_tnc_attr_t *attr;
+ enum_name_t *pa_subtype_names;
+ pen_type_t type, msg_type;
+ TNC_Result result;
+ bool fatal_error = FALSE, assessment = FALSE;
+ enumerator_t *enumerator;
+
+ hcd_state = (imv_hcd_state_t*)state;
+
+ /* generate an outgoing PA-TNC message - we might need it */
+ out_msg = imv_msg_create_as_reply(in_msg);
+
+ /* parse received PA-TNC message and handle local and remote errors */
+ result = in_msg->receive(in_msg,out_msg, &fatal_error);
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ out_msg->destroy(out_msg);
+ return result;
+ }
+ msg_type = in_msg->get_msg_type(in_msg);
+ pa_subtype_names = get_pa_subtype_names(msg_type.vendor_id);
+ DBG2(DBG_IMV, "received attributes for PA subtype %N/%N",
+ pen_names, msg_type.vendor_id, pa_subtype_names, msg_type.type);
+
+ /* set current subtype */
+ if (msg_type.vendor_id == PEN_IETF)
+ {
+ hcd_state->set_subtype(hcd_state, PA_SUBTYPE_PWG_HCD_SYSTEM);
+ }
+ else
+ {
+ hcd_state->set_subtype(hcd_state, msg_type.type);
+ }
+
+ /* analyze PA-TNC attributes */
+ enumerator = in_msg->create_attribute_enumerator(in_msg);
+ while (enumerator->enumerate(enumerator, &attr))
+ {
+ type = attr->get_type(attr);
+
+ if (type.vendor_id == PEN_IETF)
+ {
+ switch (type.type)
+ {
+ case IETF_ATTR_FORWARDING_ENABLED:
+ {
+ ietf_attr_fwd_enabled_t *attr_cast;
+ os_fwd_status_t fwd_status;
+
+ attr_cast = (ietf_attr_fwd_enabled_t*)attr;
+ fwd_status = attr_cast->get_status(attr_cast);
+ DBG2(DBG_IMV, " %N: %N", ietf_attr_names, type.type,
+ os_fwd_status_names, fwd_status);
+ state->set_action_flags(state,
+ IMV_HCD_ATTR_FORWARDING_ENABLED);
+ break;
+ }
+ case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED:
+ {
+ generic_attr_bool_t *attr_cast;
+ bool status;
+
+ attr_cast = (generic_attr_bool_t*)attr;
+ status = attr_cast->get_status(attr_cast);
+ DBG2(DBG_IMV, " %N: %s", ietf_attr_names, type.type,
+ status ? "yes" : "no");
+ state->set_action_flags(state,
+ IMV_HCD_ATTR_DEFAULT_PWD_ENABLED);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else if (type.vendor_id == PEN_PWG)
+ {
+ state->set_action_flags(state, attr_type_to_flag(type.type));
+
+ switch (type.type)
+ {
+ case PWG_HCD_ATTRS_NATURAL_LANG:
+ case PWG_HCD_MACHINE_TYPE_MODEL:
+ case PWG_HCD_VENDOR_NAME:
+ case PWG_HCD_TIME_SOURCE:
+ case PWG_HCD_FIRMWARE_NAME:
+ case PWG_HCD_FIRMWARE_STRING_VERSION:
+ case PWG_HCD_RESIDENT_APP_NAME:
+ case PWG_HCD_RESIDENT_APP_STRING_VERSION:
+ case PWG_HCD_USER_APP_NAME:
+ case PWG_HCD_USER_APP_STRING_VERSION:
+ {
+ chunk_t value;
+
+ value = attr->get_value(attr);
+ DBG2(DBG_IMV, " %N: %.*s", pwg_attr_names, type.type,
+ value.len, value.ptr);
+ break;
+ }
+ case PWG_HCD_FIRMWARE_PATCHES:
+ case PWG_HCD_RESIDENT_APP_PATCHES:
+ case PWG_HCD_USER_APP_PATCHES:
+ {
+ chunk_t value;
+ size_t len;
+
+ value = attr->get_value(attr);
+ len = value.len;
+
+ /* remove any trailing LF from patches string */
+ if (len && (value.ptr[len - 1] == '\n'))
+ {
+ len--;
+ }
+ DBG2(DBG_IMV, " %N:%s%.*s", pwg_attr_names, type.type,
+ len ? "\n" : " ", len, value.ptr);
+ break;
+ }
+ case PWG_HCD_FIRMWARE_VERSION:
+ case PWG_HCD_RESIDENT_APP_VERSION:
+ case PWG_HCD_USER_APP_VERSION:
+ {
+ chunk_t value;
+
+ value = attr->get_value(attr);
+ DBG2(DBG_IMV, " %N: %#B", pwg_attr_names, type.type, &value);
+ break;
+ }
+ case PWG_HCD_CERTIFICATION_STATE:
+ case PWG_HCD_CONFIGURATION_STATE:
+ {
+ chunk_t value;
+
+ value = attr->get_value(attr);
+ DBG2(DBG_IMV, " %N: %B", pwg_attr_names, type.type, &value);
+ break;
+ }
+ case PWG_HCD_DEFAULT_PWD_ENABLED:
+ case PWG_HCD_PSTN_FAX_ENABLED:
+ case PWG_HCD_USER_APP_ENABLED:
+ case PWG_HCD_USER_APP_PERSIST_ENABLED:
+ {
+ generic_attr_bool_t *attr_cast;
+ bool status;
+
+ attr_cast = (generic_attr_bool_t*)attr;
+ status = attr_cast->get_status(attr_cast);
+ DBG2(DBG_IMV, " %N: %s", pwg_attr_names, type.type,
+ status ? "yes" : "no");
+
+ if (type.type == PWG_HCD_USER_APP_ENABLED && !status)
+ {
+ /* do not request user applications */
+ hcd_state->set_user_app_disabled(hcd_state);
+ }
+ break;
+ }
+ case PWG_HCD_FORWARDING_ENABLED:
+ {
+ ietf_attr_fwd_enabled_t *attr_cast;
+ os_fwd_status_t fwd_status;
+
+ attr_cast = (ietf_attr_fwd_enabled_t*)attr;
+ fwd_status = attr_cast->get_status(attr_cast);
+ DBG2(DBG_IMV, " %N: %N", pwg_attr_names, type.type,
+ os_fwd_status_names, fwd_status);
+ break;
+ }
+
+ case PWG_HCD_VENDOR_SMI_CODE:
+ {
+ pwg_attr_vendor_smi_code_t *attr_cast;
+ uint32_t smi_code;
+
+ attr_cast = (pwg_attr_vendor_smi_code_t*)attr;
+ smi_code = attr_cast->get_vendor_smi_code(attr_cast);
+ DBG2(DBG_IMV, " %N: 0x%06x (%u)", pwg_attr_names, type.type,
+ smi_code, smi_code);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ if (fatal_error)
+ {
+ state->set_recommendation(state,
+ TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+ TNC_IMV_EVALUATION_RESULT_ERROR);
+ assessment = TRUE;
+ }
+
+ if (assessment)
+ {
+ hcd_state->set_handshake_state(hcd_state, IMV_HCD_STATE_END);
+ result = out_msg->send_assessment(out_msg);
+ if (result == TNC_RESULT_SUCCESS)
+ {
+ result = this->agent->provide_recommendation(this->agent, state);
+ }
+ }
+ else
+ {
+ /* send PA-TNC message with the EXCL flag set */
+ result = out_msg->send(out_msg, TRUE);
+ }
+ out_msg->destroy(out_msg);
+
+ return result;
+}
+
+METHOD(imv_agent_if_t, receive_message, TNC_Result,
+ private_imv_hcd_agent_t *this, TNC_ConnectionID id,
+ TNC_MessageType msg_type, chunk_t msg)
+{
+ imv_state_t *state;
+ imv_msg_t *in_msg;
+ TNC_Result result;
+
+ if (!this->agent->get_state(this->agent, id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ in_msg = imv_msg_create_from_data(this->agent, state, id, msg_type, msg);
+ result = receive_msg(this, state, in_msg);
+ in_msg->destroy(in_msg);
+
+ return result;
+}
+
+METHOD(imv_agent_if_t, receive_message_long, TNC_Result,
+ private_imv_hcd_agent_t *this, TNC_ConnectionID id,
+ TNC_UInt32 src_imc_id, TNC_UInt32 dst_imv_id,
+ TNC_VendorID msg_vid, TNC_MessageSubtype msg_subtype, chunk_t msg)
+{
+ imv_state_t *state;
+ imv_msg_t *in_msg;
+ TNC_Result result;
+
+ if (!this->agent->get_state(this->agent, id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ in_msg = imv_msg_create_from_long_data(this->agent, state, id,
+ src_imc_id, dst_imv_id, msg_vid, msg_subtype, msg);
+ result = receive_msg(this, state, in_msg);
+ in_msg->destroy(in_msg);
+
+ return result;
+
+}
+
+/**
+ * Build an IETF Attribute Request attribute for missing attributes
+ */
+static pa_tnc_attr_t* build_attr_request(uint32_t received)
+{
+ pa_tnc_attr_t *attr;
+ ietf_attr_attr_request_t *attr_cast;
+
+ attr = ietf_attr_attr_request_create(PEN_RESERVED, 0);
+ attr_cast = (ietf_attr_attr_request_t*)attr;
+
+ if (!(received & IMV_HCD_ATTR_NATURAL_LANG))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_ATTRS_NATURAL_LANG);
+ }
+ if (!(received & IMV_HCD_ATTR_DEFAULT_PWD_ENABLED))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_DEFAULT_PWD_ENABLED);
+ }
+ if (!(received & IMV_HCD_ATTR_FIREWALL_SETTING))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_FIREWALL_SETTING);
+ }
+ if (!(received & IMV_HCD_ATTR_FIRMWARE_NAME))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_FIRMWARE_NAME);
+ }
+ if (!(received & IMV_HCD_ATTR_FORWARDING_ENABLED))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_FORWARDING_ENABLED);
+ }
+ if (!(received & IMV_HCD_ATTR_MACHINE_TYPE_MODEL))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_MACHINE_TYPE_MODEL);
+ }
+ if (!(received & IMV_HCD_ATTR_PSTN_FAX_ENABLED))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_PSTN_FAX_ENABLED);
+ }
+ if (!(received & IMV_HCD_ATTR_RESIDENT_APP_NAME))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_RESIDENT_APP_NAME);
+ }
+ if (!(received & IMV_HCD_ATTR_TIME_SOURCE))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_TIME_SOURCE);
+ }
+ if (!(received & IMV_HCD_ATTR_USER_APP_ENABLED))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_USER_APP_ENABLED);
+ }
+ if (!(received & IMV_HCD_ATTR_USER_APP_PERSIST_ENABLED))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_USER_APP_PERSIST_ENABLED);
+ }
+ if (!(received & IMV_HCD_ATTR_USER_APP_NAME))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_USER_APP_NAME);
+ }
+ if (!(received & IMV_HCD_ATTR_VENDOR_NAME))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_VENDOR_NAME);
+ }
+ if (!(received & IMV_HCD_ATTR_VENDOR_SMI_CODE))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_VENDOR_SMI_CODE);
+ }
+ if (!(received & IMV_HCD_ATTR_CERTIFICATION_STATE))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_CERTIFICATION_STATE);
+ }
+ if (!(received & IMV_HCD_ATTR_CONFIGURATION_STATE))
+ {
+ attr_cast->add(attr_cast, PEN_PWG, PWG_HCD_CONFIGURATION_STATE);
+ }
+ return attr;
+}
+
+METHOD(imv_agent_if_t, batch_ending, TNC_Result,
+ private_imv_hcd_agent_t *this, TNC_ConnectionID id)
+{
+ imv_msg_t *out_msg;
+ imv_state_t *state;
+ imv_hcd_state_t *hcd_state;
+ imv_hcd_handshake_state_t handshake_state;
+ pa_tnc_attr_t *attr;
+ TNC_IMVID imv_id;
+ TNC_Result result = TNC_RESULT_SUCCESS;
+
+ if (!this->agent->get_state(this->agent, id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ hcd_state = (imv_hcd_state_t*)state;
+ handshake_state = hcd_state->get_handshake_state(hcd_state);
+ imv_id = this->agent->get_id(this->agent);
+
+ if (handshake_state == IMV_HCD_STATE_END)
+ {
+ return TNC_RESULT_SUCCESS;
+ }
+
+ if (handshake_state == IMV_HCD_STATE_INIT)
+ {
+ size_t max_attr_size = HCD_MAX_ATTR_SIZE;
+ size_t max_seg_size;
+ seg_contract_t *contract;
+ seg_contract_manager_t *contracts;
+ char buf[BUF_LEN];
+ uint32_t received;
+ int i;
+
+ /* Determine maximum PA-TNC attribute segment size */
+ max_seg_size = state->get_max_msg_len(state)
+ - PA_TNC_HEADER_SIZE
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_SEG_ENV_HEADER
+ - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+ contracts = state->get_contracts(state);
+
+ for (i = 1; i < countof(msg_types); i++)
+ {
+ out_msg = imv_msg_create(this->agent, state, id, imv_id,
+ TNC_IMCID_ANY, msg_types[i]);
+
+ /* Announce support of PA-TNC segmentation to IMC */
+ contract = seg_contract_create(msg_types[i], max_attr_size,
+ max_seg_size, TRUE, imv_id, FALSE);
+ contract->get_info_string(contract, buf, BUF_LEN, TRUE);
+ DBG2(DBG_IMV, "%s", buf);
+ contracts->add_contract(contracts, contract);
+ attr = tcg_seg_attr_max_size_create(max_attr_size, max_seg_size,
+ TRUE);
+ out_msg->add_attribute(out_msg, attr);
+
+ hcd_state->set_subtype(hcd_state, msg_types[i].type);
+ received = state->get_action_flags(state);
+
+ if ((received & IMV_HCD_ATTR_MUST) != IMV_HCD_ATTR_MUST)
+ {
+ /* create attribute request for missing mandatory attributes */
+ out_msg->add_attribute(out_msg, build_attr_request(received));
+ }
+ result = out_msg->send(out_msg, FALSE);
+ out_msg->destroy(out_msg);
+
+ if (result != TNC_RESULT_SUCCESS)
+ {
+ break;
+ }
+ }
+ hcd_state->set_handshake_state(hcd_state, IMV_HCD_STATE_ATTR_REQ);
+ }
+
+ return result;
+}
+
+METHOD(imv_agent_if_t, solicit_recommendation, TNC_Result,
+ private_imv_hcd_agent_t *this, TNC_ConnectionID id)
+{
+ imv_state_t *state;
+ imv_hcd_state_t* hcd_state;
+ imv_hcd_handshake_state_t handshake_state;
+ enum_name_t *pa_subtype_names;
+ bool missing = FALSE;
+ uint32_t received;
+ int i;
+
+ if (!this->agent->get_state(this->agent, id, &state))
+ {
+ return TNC_RESULT_FATAL;
+ }
+ hcd_state = (imv_hcd_state_t*)state;
+ handshake_state = hcd_state->get_handshake_state(hcd_state);
+
+ if (handshake_state == IMV_HCD_STATE_ATTR_REQ)
+ {
+ pa_subtype_names = get_pa_subtype_names(PEN_PWG);
+
+ for (i = 1; i < countof(msg_types); i++)
+ {
+ hcd_state->set_subtype(hcd_state, msg_types[i].type);
+ received = state->get_action_flags(state);
+ if ((received & IMV_HCD_ATTR_MUST) != IMV_HCD_ATTR_MUST)
+ {
+ DBG1(DBG_IMV, "missing attributes for PA subtype %N/%N",
+ pen_names, PEN_PWG, pa_subtype_names, msg_types[i].type);
+ missing = TRUE;
+ }
+ }
+
+ if (missing)
+ {
+ state->set_recommendation(state,
+ TNC_IMV_ACTION_RECOMMENDATION_NO_ACCESS ,
+ TNC_IMV_EVALUATION_RESULT_NONCOMPLIANT_MAJOR);
+ }
+ else
+ {
+ state->set_recommendation(state,
+ TNC_IMV_ACTION_RECOMMENDATION_ALLOW ,
+ TNC_IMV_EVALUATION_RESULT_COMPLIANT);
+ }
+ }
+ hcd_state->set_handshake_state(hcd_state, IMV_HCD_STATE_END);
+
+ return this->agent->provide_recommendation(this->agent, state);
+}
+
+METHOD(imv_agent_if_t, destroy, void,
+ private_imv_hcd_agent_t *this)
+{
+ DESTROY_IF(this->agent);
+ free(this);
+}
+
+/**
+ * Described in header.
+ */
+imv_agent_if_t *imv_hcd_agent_create(const char *name, TNC_IMVID id,
+ TNC_Version *actual_version)
+{
+ private_imv_hcd_agent_t *this;
+ imv_agent_t *agent;
+
+ agent = imv_agent_create(name, msg_types, countof(msg_types), id,
+ actual_version);
+ if (!agent)
+ {
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .bind_functions = _bind_functions,
+ .notify_connection_change = _notify_connection_change,
+ .receive_message = _receive_message,
+ .receive_message_long = _receive_message_long,
+ .batch_ending = _batch_ending,
+ .solicit_recommendation = _solicit_recommendation,
+ .destroy = _destroy,
+ },
+ .agent = agent,
+ );
+
+ return &this->public;
+}
+
diff --git a/src/libimcv/plugins/imv_hcd/imv_hcd_agent.h b/src/libimcv/plugins/imv_hcd/imv_hcd_agent.h
new file mode 100644
index 000000000..d4e2e3f0e
--- /dev/null
+++ b/src/libimcv/plugins/imv_hcd/imv_hcd_agent.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 imv_hcd_agent_t imv_hcd_agent
+ * @{ @ingroup imv_hcd
+ */
+
+#ifndef IMV_HCD_AGENT_H_
+#define IMV_HCD_AGENT_H_
+
+#include <imv/imv_agent_if.h>
+
+/**
+ * Creates a HCD IMV agent
+ *
+ * @param name Name of the IMV
+ * @param id ID of the IMV
+ * @param actual_version TNC IF-IMV version
+ */
+imv_agent_if_t* imv_hcd_agent_create(const char* name, TNC_IMVID id,
+ TNC_Version *actual_version);
+
+#endif /** IMV_HCD_AGENT_H_ @}*/
diff --git a/src/libimcv/plugins/imv_hcd/imv_hcd_state.c b/src/libimcv/plugins/imv_hcd/imv_hcd_state.c
new file mode 100644
index 000000000..bfe6dd619
--- /dev/null
+++ b/src/libimcv/plugins/imv_hcd/imv_hcd_state.c
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 "imv_hcd_state.h"
+#include "imv/imv_lang_string.h"
+#include "imv/imv_reason_string.h"
+
+#include <tncif_policy.h>
+
+#include <utils/debug.h>
+
+typedef struct private_imv_hcd_state_t private_imv_hcd_state_t;
+typedef struct subtype_action_flags_t subtype_action_flags_t;
+
+struct subtype_action_flags_t {
+ pa_subtype_pwg_t subtype;
+ uint32_t action_flags;
+};
+
+/**
+ * Private data of an imv_hcd_state_t object.
+ */
+struct private_imv_hcd_state_t {
+
+ /**
+ * Public members of imv_hcd_state_t
+ */
+ imv_hcd_state_t public;
+
+ /**
+ * TNCCS connection ID
+ */
+ TNC_ConnectionID connection_id;
+
+ /**
+ * TNCCS connection state
+ */
+ TNC_ConnectionState state;
+
+ /**
+ * Does the TNCCS connection support long message types?
+ */
+ bool has_long;
+
+ /**
+ * Does the TNCCS connection support exclusive delivery?
+ */
+ bool has_excl;
+
+ /**
+ * Maximum PA-TNC message size for this TNCCS connection
+ */
+ uint32_t max_msg_len;
+
+ /**
+ * Current flags set for completed actions
+ */
+ uint32_t *action_flags;
+
+ /**
+ * Action flags for all PA subtypes
+ */
+ subtype_action_flags_t subtype_action_flags[6];
+
+ /**
+ * IMV database session associated with TNCCS connection
+ */
+ imv_session_t *session;
+
+ /**
+ * PA-TNC attribute segmentation contracts associated with TNCCS connection
+ */
+ seg_contract_manager_t *contracts;
+
+ /**
+ * IMV action recommendation
+ */
+ TNC_IMV_Action_Recommendation rec;
+
+ /**
+ * IMV evaluation result
+ */
+ TNC_IMV_Evaluation_Result eval;
+
+ /**
+ * IMV OS handshake state
+ */
+ imv_hcd_handshake_state_t handshake_state;
+
+ /**
+ * TNC Reason String
+ */
+ imv_reason_string_t *reason_string;
+
+};
+
+/**
+ * Supported languages
+ */
+static char* languages[] = { "en", "de", "fr", "pl" };
+
+/**
+ * Reason strings for "Port Filter"
+ */
+static imv_lang_string_t reasons[] = {
+ { "en", "Mandatory HCD attributes are missing" },
+ { "de", "Obligatorische HCD Attribute fehlen" },
+ { "fr", "Il manque des attributes HCD obligatoires" },
+ { "pl", "Brakuje atrybutów obowiązkowych" },
+ { NULL, NULL }
+};
+
+METHOD(imv_state_t, get_connection_id, TNC_ConnectionID,
+ private_imv_hcd_state_t *this)
+{
+ return this->connection_id;
+}
+
+METHOD(imv_state_t, has_long, bool,
+ private_imv_hcd_state_t *this)
+{
+ return this->has_long;
+}
+
+METHOD(imv_state_t, has_excl, bool,
+ private_imv_hcd_state_t *this)
+{
+ return this->has_excl;
+}
+
+METHOD(imv_state_t, set_flags, void,
+ private_imv_hcd_state_t *this, bool has_long, bool has_excl)
+{
+ this->has_long = has_long;
+ this->has_excl = has_excl;
+}
+
+METHOD(imv_state_t, set_max_msg_len, void,
+ private_imv_hcd_state_t *this, uint32_t max_msg_len)
+{
+ this->max_msg_len = max_msg_len;
+}
+
+METHOD(imv_state_t, get_max_msg_len, uint32_t,
+ private_imv_hcd_state_t *this)
+{
+ return this->max_msg_len;
+}
+
+METHOD(imv_state_t, set_action_flags, void,
+ private_imv_hcd_state_t *this, uint32_t flags)
+{
+ *this->action_flags |= flags;
+}
+
+METHOD(imv_state_t, get_action_flags, uint32_t,
+ private_imv_hcd_state_t *this)
+{
+ return *this->action_flags;
+}
+
+METHOD(imv_state_t, set_session, void,
+ private_imv_hcd_state_t *this, imv_session_t *session)
+{
+ this->session = session;
+}
+
+METHOD(imv_state_t, get_session, imv_session_t*,
+ private_imv_hcd_state_t *this)
+{
+ return this->session;
+}
+
+METHOD(imv_state_t, get_contracts, seg_contract_manager_t*,
+ private_imv_hcd_state_t *this)
+{
+ return this->contracts;
+}
+
+METHOD(imv_state_t, get_recommendation, void,
+ private_imv_hcd_state_t *this, TNC_IMV_Action_Recommendation *rec,
+ TNC_IMV_Evaluation_Result *eval)
+{
+ *rec = this->rec;
+ *eval = this->eval;
+}
+
+METHOD(imv_state_t, set_recommendation, void,
+ private_imv_hcd_state_t *this, TNC_IMV_Action_Recommendation rec,
+ TNC_IMV_Evaluation_Result eval)
+{
+ this->rec = rec;
+ this->eval = eval;
+}
+
+METHOD(imv_state_t, update_recommendation, void,
+ private_imv_hcd_state_t *this, TNC_IMV_Action_Recommendation rec,
+ TNC_IMV_Evaluation_Result eval)
+{
+ this->rec = tncif_policy_update_recommendation(this->rec, rec);
+ this->eval = tncif_policy_update_evaluation(this->eval, eval);
+}
+
+METHOD(imv_state_t, change_state, void,
+ private_imv_hcd_state_t *this, TNC_ConnectionState new_state)
+{
+ this->state = new_state;
+}
+
+METHOD(imv_state_t, get_reason_string, bool,
+ private_imv_hcd_state_t *this, enumerator_t *language_enumerator,
+ chunk_t *reason_string, char **reason_language)
+{
+ if (this->rec == TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION)
+ {
+ return FALSE;
+ }
+ *reason_language = imv_lang_string_select_lang(language_enumerator,
+ languages, countof(languages));
+
+ /* Instantiate a TNC Reason String object */
+ DESTROY_IF(this->reason_string);
+ this->reason_string = imv_reason_string_create(*reason_language, "\n");
+ this->reason_string->add_reason(this->reason_string, reasons);
+ *reason_string = this->reason_string->get_encoding(this->reason_string);
+
+ return TRUE;
+}
+
+METHOD(imv_state_t, get_remediation_instructions, bool,
+ private_imv_hcd_state_t *this, enumerator_t *language_enumerator,
+ chunk_t *string, char **lang_code, char **uri)
+{
+ return FALSE;
+}
+
+METHOD(imv_state_t, destroy, void,
+ private_imv_hcd_state_t *this)
+{
+ DESTROY_IF(this->session);
+ DESTROY_IF(this->reason_string);
+ this->contracts->destroy(this->contracts);
+ free(this);
+}
+
+METHOD(imv_hcd_state_t, set_handshake_state, void,
+ private_imv_hcd_state_t *this, imv_hcd_handshake_state_t new_state)
+{
+ this->handshake_state = new_state;
+}
+
+METHOD(imv_hcd_state_t, get_handshake_state, imv_hcd_handshake_state_t,
+ private_imv_hcd_state_t *this)
+{
+ return this->handshake_state;
+}
+
+METHOD(imv_hcd_state_t, set_subtype, void,
+ private_imv_hcd_state_t *this, pa_subtype_pwg_t subtype)
+{
+ int i;
+
+ for (i = 0; i < countof(this->subtype_action_flags); i++)
+ {
+ if (subtype == this->subtype_action_flags[i].subtype)
+ {
+ this->action_flags = &this->subtype_action_flags[i].action_flags;
+ break;
+ }
+ }
+}
+
+METHOD(imv_hcd_state_t, set_user_app_disabled, void,
+ private_imv_hcd_state_t *this)
+{
+ int i;
+
+ for (i = 0; i < countof(this->subtype_action_flags); i++)
+ {
+ this->subtype_action_flags[i].action_flags |= IMV_HCD_ATTR_USER_APP_NAME;
+ }
+}
+
+/**
+ * Described in header.
+ */
+imv_state_t *imv_hcd_state_create(TNC_ConnectionID connection_id)
+{
+ private_imv_hcd_state_t *this;
+
+ INIT(this,
+ .public = {
+ .interface = {
+ .get_connection_id = _get_connection_id,
+ .has_long = _has_long,
+ .has_excl = _has_excl,
+ .set_flags = _set_flags,
+ .set_max_msg_len = _set_max_msg_len,
+ .get_max_msg_len = _get_max_msg_len,
+ .set_action_flags = _set_action_flags,
+ .get_action_flags = _get_action_flags,
+ .set_session = _set_session,
+ .get_session = _get_session,
+ .get_contracts = _get_contracts,
+ .change_state = _change_state,
+ .get_recommendation = _get_recommendation,
+ .set_recommendation = _set_recommendation,
+ .update_recommendation = _update_recommendation,
+ .get_reason_string = _get_reason_string,
+ .get_remediation_instructions = _get_remediation_instructions,
+ .destroy = _destroy,
+ },
+ .set_handshake_state = _set_handshake_state,
+ .get_handshake_state = _get_handshake_state,
+ .set_subtype = _set_subtype,
+ .set_user_app_disabled = _set_user_app_disabled,
+ },
+ .state = TNC_CONNECTION_STATE_CREATE,
+ .rec = TNC_IMV_ACTION_RECOMMENDATION_NO_RECOMMENDATION,
+ .eval = TNC_IMV_EVALUATION_RESULT_DONT_KNOW,
+ .connection_id = connection_id,
+ .contracts = seg_contract_manager_create(),
+ .subtype_action_flags = {
+ { PA_SUBTYPE_PWG_HCD_SYSTEM, IMV_HCD_ATTR_NONE },
+ { PA_SUBTYPE_PWG_HCD_CONSOLE, IMV_HCD_ATTR_SYSTEM_ONLY },
+ { PA_SUBTYPE_PWG_HCD_MARKER, IMV_HCD_ATTR_SYSTEM_ONLY },
+ { PA_SUBTYPE_PWG_HCD_FINISHER, IMV_HCD_ATTR_SYSTEM_ONLY },
+ { PA_SUBTYPE_PWG_HCD_INTERFACE, IMV_HCD_ATTR_SYSTEM_ONLY },
+ { PA_SUBTYPE_PWG_HCD_SCANNER, IMV_HCD_ATTR_SYSTEM_ONLY },
+ }
+ );
+
+ this->action_flags = &this->subtype_action_flags[0].action_flags;
+
+ return &this->public.interface;
+}
+
+
diff --git a/src/libimcv/plugins/imv_hcd/imv_hcd_state.h b/src/libimcv/plugins/imv_hcd/imv_hcd_state.h
new file mode 100644
index 000000000..dce9b3098
--- /dev/null
+++ b/src/libimcv/plugins/imv_hcd/imv_hcd_state.h
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 imv_hcd imv_hcd
+ * @ingroup libimcv_plugins
+ *
+ * @defgroup imv_hcd_state_t imv_hcd_state
+ * @{ @ingroup imv_hcd
+ */
+
+#ifndef IMV_HCD_STATE_H_
+#define IMV_HCD_STATE_H_
+
+#include <imv/imv_state.h>
+#include <library.h>
+
+#include <tncif_pa_subtypes.h>
+
+typedef struct imv_hcd_state_t imv_hcd_state_t;
+typedef enum imv_hcd_attr_t imv_hcd_attr_t;
+typedef enum imv_hcd_handshake_state_t imv_hcd_handshake_state_t;
+typedef enum os_settings_t os_settings_t;
+
+/**
+ * Flag set when corresponding attribute has been received
+ */
+enum imv_hcd_attr_t {
+ IMV_HCD_ATTR_NONE = 0,
+ IMV_HCD_ATTR_DEFAULT_PWD_ENABLED = (1<<0),
+ IMV_HCD_ATTR_FIREWALL_SETTING = (1<<1),
+ IMV_HCD_ATTR_FORWARDING_ENABLED = (1<<2),
+ IMV_HCD_ATTR_MACHINE_TYPE_MODEL = (1<<3),
+ IMV_HCD_ATTR_PSTN_FAX_ENABLED = (1<<4),
+ IMV_HCD_ATTR_TIME_SOURCE = (1<<5),
+ IMV_HCD_ATTR_USER_APP_ENABLED = (1<<6),
+ IMV_HCD_ATTR_USER_APP_PERSIST_ENABLED = (1<<7),
+ IMV_HCD_ATTR_VENDOR_NAME = (1<<8),
+ IMV_HCD_ATTR_VENDOR_SMI_CODE = (1<<9),
+ IMV_HCD_ATTR_CERTIFICATION_STATE = (1<<10),
+ IMV_HCD_ATTR_CONFIGURATION_STATE = (1<<11),
+
+ IMV_HCD_ATTR_SYSTEM_ONLY = (1<<12)-1,
+
+ IMV_HCD_ATTR_NATURAL_LANG = (1<<12),
+ IMV_HCD_ATTR_FIRMWARE_NAME = (1<<13),
+ IMV_HCD_ATTR_RESIDENT_APP_NAME = (1<<14),
+ IMV_HCD_ATTR_USER_APP_NAME = (1<<15),
+
+ IMV_HCD_ATTR_MUST = (1<<16)-1
+};
+
+/**
+ * IMV OS Handshake States (state machine)
+ */
+enum imv_hcd_handshake_state_t {
+ IMV_HCD_STATE_INIT,
+ IMV_HCD_STATE_ATTR_REQ,
+ IMV_HCD_STATE_END
+};
+
+/**
+ * Internal state of an imv_hcd_t connection instance
+ */
+struct imv_hcd_state_t {
+
+ /**
+ * imv_state_t interface
+ */
+ imv_state_t interface;
+
+ /**
+ * Set state of the handshake
+ *
+ * @param new_state the handshake state of IMV
+ */
+ void (*set_handshake_state)(imv_hcd_state_t *this,
+ imv_hcd_handshake_state_t new_state);
+
+ /**
+ * Get state of the handshake
+ *
+ * @return the handshake state of IMV
+ */
+ imv_hcd_handshake_state_t (*get_handshake_state)(imv_hcd_state_t *this);
+
+ /**
+ * Set the PWG HCD PA subtype currently being handled
+ *
+ * @param subtype PWG HCD PA subtype
+ */
+ void (*set_subtype)(imv_hcd_state_t *this, pa_subtype_pwg_t subtype);
+
+ /**
+ * Set User Application Disabled
+ */
+ void (*set_user_app_disabled)(imv_hcd_state_t *this);
+
+};
+
+/**
+ * Create an imv_hcd_state_t instance
+ *
+ * @param id connection ID
+ */
+imv_state_t* imv_hcd_state_create(TNC_ConnectionID id);
+
+#endif /** IMV_HCD_STATE_H_ @}*/
diff --git a/src/libimcv/plugins/imv_os/imv_os_agent.c b/src/libimcv/plugins/imv_os/imv_os_agent.c
index f0b1936ab..4bf6c7e21 100644
--- a/src/libimcv/plugins/imv_os/imv_os_agent.c
+++ b/src/libimcv/plugins/imv_os/imv_os_agent.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 Andreas Steffen
+ * Copyright (C) 2013-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -23,10 +23,10 @@
#include <imcv.h>
#include <imv/imv_agent.h>
#include <imv/imv_msg.h>
+#include <generic/generic_attr_bool.h>
+#include <generic/generic_attr_string.h>
#include <ietf/ietf_attr.h>
#include <ietf/ietf_attr_attr_request.h>
-#include <ietf/ietf_attr_default_pwd_enabled.h>
-#include <ietf/ietf_attr_fwd_enabled.h>
#include <ietf/ietf_attr_installed_packages.h>
#include <ietf/ietf_attr_numeric_version.h>
#include <ietf/ietf_attr_op_status.h>
@@ -37,7 +37,6 @@
#include <ita/ita_attr.h>
#include <ita/ita_attr_get_settings.h>
#include <ita/ita_attr_settings.h>
-#include <ita/ita_attr_device_id.h>
#include "tcg/seg/tcg_seg_attr_max_size.h"
#include "tcg/seg/tcg_seg_attr_seg_env.h"
@@ -270,12 +269,12 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
}
case IETF_ATTR_FORWARDING_ENABLED:
{
- ietf_attr_fwd_enabled_t *attr_cast;
+ generic_attr_bool_t *attr_cast;
os_fwd_status_t fwd_status;
state->set_action_flags(state,
IMV_OS_ATTR_FORWARDING_ENABLED);
- attr_cast = (ietf_attr_fwd_enabled_t*)attr;
+ attr_cast = (generic_attr_bool_t*)attr;
fwd_status = attr_cast->get_status(attr_cast);
DBG1(DBG_IMV, "IPv4 forwarding is %N",
os_fwd_status_names, fwd_status);
@@ -288,12 +287,12 @@ static TNC_Result receive_msg(private_imv_os_agent_t *this, imv_state_t *state,
}
case IETF_ATTR_FACTORY_DEFAULT_PWD_ENABLED:
{
- ietf_attr_default_pwd_enabled_t *attr_cast;
+ generic_attr_bool_t *attr_cast;
bool default_pwd_status;
state->set_action_flags(state,
IMV_OS_ATTR_FACTORY_DEFAULT_PWD_ENABLED);
- attr_cast = (ietf_attr_default_pwd_enabled_t*)attr;
+ attr_cast = (generic_attr_bool_t*)attr;
default_pwd_status = attr_cast->get_status(attr_cast);
DBG1(DBG_IMV, "factory default password is %sabled",
default_pwd_status ? "en":"dis");
@@ -542,9 +541,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
max_seg_size = state->get_max_msg_len(state)
- PA_TNC_HEADER_SIZE
- PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_SEG_ENV_HEADER
- - PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+ - TCG_SEG_ATTR_SEG_ENV_HEADER;
/* Announce support of PA-TNC segmentation to IMC */
contract = seg_contract_create(msg_types[0], max_attr_size,
diff --git a/src/libimcv/plugins/imv_os/pacman.c b/src/libimcv/plugins/imv_os/pacman.c
index 019e2adb8..fbcab5eba 100644
--- a/src/libimcv/plugins/imv_os/pacman.c
+++ b/src/libimcv/plugins/imv_os/pacman.c
@@ -104,8 +104,14 @@ static void cleanup(void)
static void usage(void)
{
- printf("Usage:\n"
- "ipsec pacman --product <name> --file <filename> [--update]\n");
+ printf("Parses package information files from Debian/Ubuntu repositories and\n");
+ printf("stores the extracted information in the database used by the OS IMV.\n\n");
+ printf("ipsec pacman --product <name> --file <filename> [--security]\n\n");
+ printf(" --help print usage information\n");
+ printf(" --product <name> name of the Debian/Ubuntu release, as stored in the DB\n");
+ printf(" --file <filename> package information file to parse\n");
+ printf(" --security set this when parsing a file with security updates\n");
+ printf("\n");
}
/**
@@ -396,6 +402,17 @@ static void process_packages(char *filename, char *product, bool security)
pacman_state = PACMAN_STATE_BEGIN_PACKAGE;
}
}
+ switch (pacman_state)
+ {
+ case PACMAN_STATE_END_PACKAGE:
+ free(version);
+ /* fall-through */
+ case PACMAN_STATE_VERSION:
+ free(package);
+ break;
+ default:
+ break;
+ }
fclose(file);
db->destroy(db);
diff --git a/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c b/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c
index cbabc80bf..acef11cad 100644
--- a/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c
+++ b/src/libimcv/plugins/imv_scanner/imv_scanner_agent.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 Andreas Steffen
+ * Copyright (C) 2013-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -35,7 +35,7 @@ typedef struct private_imv_scanner_agent_t private_imv_scanner_agent_t;
/* Subscribed PA-TNC message subtypes */
static pen_type_t msg_types[] = {
- { PEN_IETF, PA_SUBTYPE_IETF_VPN }
+ { PEN_IETF, PA_SUBTYPE_IETF_FIREWALL }
};
/**
diff --git a/src/libimcv/plugins/imv_swid/imv_swid_agent.c b/src/libimcv/plugins/imv_swid/imv_swid_agent.c
index 5bebf32c0..6d327830f 100644
--- a/src/libimcv/plugins/imv_swid/imv_swid_agent.c
+++ b/src/libimcv/plugins/imv_swid/imv_swid_agent.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 Andreas Steffen
+ * Copyright (C) 2013-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -446,9 +446,7 @@ METHOD(imv_agent_if_t, batch_ending, TNC_Result,
max_seg_size = state->get_max_msg_len(state)
- PA_TNC_HEADER_SIZE
- PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_SEG_ENV_HEADER
- - PA_TNC_ATTR_HEADER_SIZE
- - TCG_SEG_ATTR_MAX_SIZE_SIZE;
+ - TCG_SEG_ATTR_SEG_ENV_HEADER;
/* Announce support of PA-TNC segmentation to IMC */
contract = seg_contract_create(msg_types[0], max_attr_size,
diff --git a/src/libimcv/pwg/pwg_attr.c b/src/libimcv/pwg/pwg_attr.c
new file mode 100644
index 000000000..8a2eb2828
--- /dev/null
+++ b/src/libimcv/pwg/pwg_attr.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 "pwg_attr.h"
+
+#include "generic/generic_attr_bool.h"
+#include "generic/generic_attr_chunk.h"
+#include "generic/generic_attr_string.h"
+#include "ietf/ietf_attr_fwd_enabled.h"
+#include "ietf/ietf_attr_port_filter.h"
+#include "pwg/pwg_attr_vendor_smi_code.h"
+
+ENUM_BEGIN(pwg_attr_names, PWG_HCD_ATTRS_NATURAL_LANG,
+ PWG_HCD_VENDOR_SMI_CODE,
+ "HCD AttributesNaturalLanguage",
+ "HCD MachineTypeModel",
+ "HCD VendorName",
+ "HCD VendorSMICode");
+ENUM_NEXT(pwg_attr_names, PWG_HCD_DEFAULT_PWD_ENABLED,
+ PWG_HCD_FORWARDING_ENABLED,
+ PWG_HCD_VENDOR_SMI_CODE,
+ "HCD DefaultPasswordEnabled",
+ "HCD FirewallSetting",
+ "HCD ForwardingEnabled");
+ENUM_NEXT(pwg_attr_names, PWG_HCD_PSTN_FAX_ENABLED,
+ PWG_HCD_PSTN_FAX_ENABLED,
+ PWG_HCD_FORWARDING_ENABLED,
+ "HCD PSTNFaxEnabled");
+ENUM_NEXT(pwg_attr_names, PWG_HCD_TIME_SOURCE,
+ PWG_HCD_TIME_SOURCE,
+ PWG_HCD_PSTN_FAX_ENABLED,
+ "HCD TimeSource");
+ENUM_NEXT(pwg_attr_names, PWG_HCD_FIRMWARE_NAME,
+ PWG_HCD_FIRMWARE_VERSION,
+ PWG_HCD_TIME_SOURCE,
+ "HCD FirmwareName",
+ "HCD FirmwarePatches",
+ "HCD FirmwareStringVersion",
+ "HCD FirmwareVersion");
+ENUM_NEXT(pwg_attr_names, PWG_HCD_RESIDENT_APP_NAME,
+ PWG_HCD_RESIDENT_APP_VERSION,
+ PWG_HCD_FIRMWARE_VERSION,
+ "HCD ResidentApplicationName",
+ "HCD ResidentApplicationPatches",
+ "HCD ResidentApplicationStringVersion",
+ "HCD ResidentApplicationVersion");
+ENUM_NEXT(pwg_attr_names, PWG_HCD_USER_APP_NAME,
+ PWG_HCD_USER_APP_PERSIST_ENABLED,
+ PWG_HCD_RESIDENT_APP_VERSION,
+ "HCD UserApplicationName",
+ "HCD UserApplicationPatches",
+ "HCD UserApplicationStringVersion",
+ "HCD UserApplicationVersion",
+ "HCD UserApplicationEnabled",
+ "HCD UserApplicationPersistenceEnabled");
+ENUM_NEXT(pwg_attr_names, PWG_HCD_CERTIFICATION_STATE,
+ PWG_HCD_CONFIGURATION_STATE,
+ PWG_HCD_USER_APP_PERSIST_ENABLED,
+ "HCD CertificationState",
+ "HCD ConfigurationState");
+ENUM_END(pwg_attr_names, PWG_HCD_CONFIGURATION_STATE);
+
+/**
+ * See header
+ */
+pa_tnc_attr_t* pwg_attr_create_from_data(u_int32_t type, size_t length, chunk_t value)
+{
+ switch (type)
+ {
+ case PWG_HCD_DEFAULT_PWD_ENABLED:
+ case PWG_HCD_USER_APP_ENABLED:
+ case PWG_HCD_USER_APP_PERSIST_ENABLED:
+ case PWG_HCD_PSTN_FAX_ENABLED:
+ return generic_attr_bool_create_from_data(length, value,
+ pen_type_create(PEN_PWG, type));
+ case PWG_HCD_ATTRS_NATURAL_LANG:
+ case PWG_HCD_MACHINE_TYPE_MODEL:
+ case PWG_HCD_VENDOR_NAME:
+ case PWG_HCD_FIRMWARE_NAME:
+ case PWG_HCD_FIRMWARE_PATCHES:
+ case PWG_HCD_FIRMWARE_STRING_VERSION:
+ case PWG_HCD_TIME_SOURCE:
+ case PWG_HCD_USER_APP_NAME:
+ case PWG_HCD_USER_APP_PATCHES:
+ case PWG_HCD_USER_APP_STRING_VERSION:
+ case PWG_HCD_RESIDENT_APP_NAME:
+ case PWG_HCD_RESIDENT_APP_PATCHES:
+ case PWG_HCD_RESIDENT_APP_STRING_VERSION:
+ return generic_attr_string_create_from_data(length, value,
+ pen_type_create(PEN_PWG, type));
+ case PWG_HCD_FIRMWARE_VERSION:
+ case PWG_HCD_RESIDENT_APP_VERSION:
+ case PWG_HCD_USER_APP_VERSION:
+ return generic_attr_chunk_create_from_data(length, value, 16,
+ pen_type_create(PEN_PWG, type));
+ case PWG_HCD_CERTIFICATION_STATE:
+ case PWG_HCD_CONFIGURATION_STATE:
+ return generic_attr_chunk_create_from_data(length, value, 0,
+ pen_type_create(PEN_PWG, type));
+ case PWG_HCD_VENDOR_SMI_CODE:
+ return pwg_attr_vendor_smi_code_create_from_data(length, value);
+ case PWG_HCD_FORWARDING_ENABLED:
+ return ietf_attr_fwd_enabled_create_from_data(length, value,
+ pen_type_create(PEN_PWG, type));
+ case PWG_HCD_FIREWALL_SETTING:
+ return ietf_attr_port_filter_create_from_data(length, value,
+ pen_type_create(PEN_PWG, type));
+ default:
+ return NULL;
+ }
+}
diff --git a/src/libimcv/pwg/pwg_attr.h b/src/libimcv/pwg/pwg_attr.h
new file mode 100644
index 000000000..01db42cd2
--- /dev/null
+++ b/src/libimcv/pwg/pwg_attr.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 pwg_attr pwg_attr
+ * @{ @ingroup libimcv
+ */
+
+#ifndef PWG_ATTR_H_
+#define PWG_ATTR_H_
+
+#include <pa_tnc/pa_tnc_attr.h>
+#include <library.h>
+
+typedef enum pwg_attr_t pwg_attr_t;
+
+/**
+ * PWG HCD IF-M Attributes (Hardcopy Device Health Assessment TNC Binding)
+ */
+enum pwg_attr_t {
+ PWG_HCD_ATTRS_NATURAL_LANG = 0x00000001, /* 1 */
+ PWG_HCD_MACHINE_TYPE_MODEL = 0x00000002, /* 2 */
+ PWG_HCD_VENDOR_NAME = 0x00000003, /* 3 */
+ PWG_HCD_VENDOR_SMI_CODE = 0x00000004, /* 4 */
+ PWG_HCD_DEFAULT_PWD_ENABLED = 0x00000014, /* 20 */
+ PWG_HCD_FIREWALL_SETTING = 0x00000015, /* 21 */
+ PWG_HCD_FORWARDING_ENABLED = 0x00000016, /* 22 */
+ PWG_HCD_PSTN_FAX_ENABLED = 0x00000028, /* 40 */
+ PWG_HCD_TIME_SOURCE = 0x00000032, /* 50 ??? */
+ PWG_HCD_FIRMWARE_NAME = 0x0000003C, /* 60 */
+ PWG_HCD_FIRMWARE_PATCHES = 0x0000003D, /* 61 */
+ PWG_HCD_FIRMWARE_STRING_VERSION = 0x0000003E, /* 62 */
+ PWG_HCD_FIRMWARE_VERSION = 0x0000003F, /* 63 */
+ PWG_HCD_RESIDENT_APP_NAME = 0x00000050, /* 80 */
+ PWG_HCD_RESIDENT_APP_PATCHES = 0x00000051, /* 81 */
+ PWG_HCD_RESIDENT_APP_STRING_VERSION = 0x00000052, /* 82 */
+ PWG_HCD_RESIDENT_APP_VERSION = 0x00000053, /* 83 */
+ PWG_HCD_USER_APP_NAME = 0x00000064, /* 100 */
+ PWG_HCD_USER_APP_PATCHES = 0x00000065, /* 101 */
+ PWG_HCD_USER_APP_STRING_VERSION = 0x00000066, /* 102 */
+ PWG_HCD_USER_APP_VERSION = 0x00000067, /* 103 */
+ PWG_HCD_USER_APP_ENABLED = 0x00000068, /* 104 */
+ PWG_HCD_USER_APP_PERSIST_ENABLED = 0x00000069, /* 105 */
+ PWG_HCD_CERTIFICATION_STATE = 0x000000C8, /* 200 */
+ PWG_HCD_CONFIGURATION_STATE = 0x000000C9, /* 201 */
+};
+
+/**
+ * enum name for pwg_attr_t.
+ */
+extern enum_name_t *pwg_attr_names;
+
+/**
+ * Create a TCG PA-TNC attribute from data
+ *
+ * @param type attribute type
+ * @param length attribute length
+ * @param value attribute value or segment
+ */
+pa_tnc_attr_t* pwg_attr_create_from_data(u_int32_t type, size_t length,
+ chunk_t value);
+
+#endif /** PWG_ATTR_H_ @}*/
diff --git a/src/libimcv/pwg/pwg_attr_vendor_smi_code.c b/src/libimcv/pwg/pwg_attr_vendor_smi_code.c
new file mode 100644
index 000000000..7931259aa
--- /dev/null
+++ b/src/libimcv/pwg/pwg_attr_vendor_smi_code.c
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 "pwg_attr_vendor_smi_code.h"
+
+#include <pa_tnc/pa_tnc_msg.h>
+#include <bio/bio_writer.h>
+#include <bio/bio_reader.h>
+#include <utils/debug.h>
+
+typedef struct private_pwg_attr_vendor_smi_code_t private_pwg_attr_vendor_smi_code_t;
+
+/**
+ * PWG HCD PA-TNC Vendor SMI Code
+ *
+ * 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
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved | Vendor SMI Code |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+
+#define VENDOR_SMI_CODE_SIZE 4
+
+/**
+ * Private data of an pwg_attr_vendor_smi_code_t object.
+ */
+struct private_pwg_attr_vendor_smi_code_t {
+
+ /**
+ * Public members of pwg_attr_vendor_smi_code_t
+ */
+ pwg_attr_vendor_smi_code_t public;
+
+ /**
+ * Vendor-specific attribute type
+ */
+ pen_type_t type;
+
+ /**
+ * Length of attribute value
+ */
+ size_t length;
+
+ /**
+ * Attribute value or segment
+ */
+ chunk_t value;
+
+ /**
+ * Noskip flag
+ */
+ bool noskip_flag;
+
+ /**
+ * Vendor SMI code
+ */
+ pen_t vendor_smi_code;
+
+ /**
+ * Reference count
+ */
+ refcount_t ref;
+};
+
+METHOD(pa_tnc_attr_t, get_type, pen_type_t,
+ private_pwg_attr_vendor_smi_code_t *this)
+{
+ return this->type;
+}
+
+METHOD(pa_tnc_attr_t, get_value, chunk_t,
+ private_pwg_attr_vendor_smi_code_t *this)
+{
+ return this->value;
+}
+
+METHOD(pa_tnc_attr_t, get_noskip_flag, bool,
+ private_pwg_attr_vendor_smi_code_t *this)
+{
+ return this->noskip_flag;
+}
+
+METHOD(pa_tnc_attr_t, set_noskip_flag,void,
+ private_pwg_attr_vendor_smi_code_t *this, bool noskip)
+{
+ this->noskip_flag = noskip;
+}
+
+METHOD(pa_tnc_attr_t, build, void,
+ private_pwg_attr_vendor_smi_code_t *this)
+{
+ bio_writer_t *writer;
+
+ if (this->value.ptr)
+ {
+ return;
+ }
+ writer = bio_writer_create(VENDOR_SMI_CODE_SIZE);
+ writer->write_uint32(writer, this->vendor_smi_code);
+
+ this->value = writer->extract_buf(writer);
+ this->length = this->value.len;
+ writer->destroy(writer);
+}
+
+METHOD(pa_tnc_attr_t, process, status_t,
+ private_pwg_attr_vendor_smi_code_t *this, u_int32_t *offset)
+{
+ bio_reader_t *reader;
+ uint32_t vendor_smi_code;
+ uint8_t reserved;
+
+ *offset = 0;
+
+ if (this->value.len < this->length)
+ {
+ return NEED_MORE;
+ }
+ if (this->value.len != VENDOR_SMI_CODE_SIZE)
+ {
+ DBG1(DBG_TNC, "incorrect attribute length for PWG HCD Vendor SMI Code");
+ return FAILED;
+ }
+ reader = bio_reader_create(this->value);
+ reader->read_uint8 (reader, &reserved);
+ reader->read_uint24(reader, &vendor_smi_code);
+ reader->destroy(reader);
+ this->vendor_smi_code = vendor_smi_code;
+
+ return SUCCESS;
+}
+
+METHOD(pa_tnc_attr_t, add_segment, void,
+ private_pwg_attr_vendor_smi_code_t *this, chunk_t segment)
+{
+ this->value = chunk_cat("mc", this->value, segment);
+}
+
+METHOD(pa_tnc_attr_t, get_ref, pa_tnc_attr_t*,
+ private_pwg_attr_vendor_smi_code_t *this)
+{
+ ref_get(&this->ref);
+ return &this->public.pa_tnc_attribute;
+}
+
+METHOD(pa_tnc_attr_t, destroy, void,
+ private_pwg_attr_vendor_smi_code_t *this)
+{
+ if (ref_put(&this->ref))
+ {
+ free(this->value.ptr);
+ free(this);
+ }
+}
+
+METHOD(pwg_attr_vendor_smi_code_t, get_vendor_smi_code, pen_t,
+ private_pwg_attr_vendor_smi_code_t *this)
+{
+ return this->vendor_smi_code;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *pwg_attr_vendor_smi_code_create(pen_t vendor_smi_code)
+{
+ private_pwg_attr_vendor_smi_code_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_vendor_smi_code = _get_vendor_smi_code,
+ },
+ .type = { PEN_PWG, PWG_HCD_VENDOR_SMI_CODE },
+ .vendor_smi_code = vendor_smi_code,
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
+/**
+ * Described in header.
+ */
+pa_tnc_attr_t *pwg_attr_vendor_smi_code_create_from_data(size_t length,
+ chunk_t data)
+{
+ private_pwg_attr_vendor_smi_code_t *this;
+
+ INIT(this,
+ .public = {
+ .pa_tnc_attribute = {
+ .get_type = _get_type,
+ .get_value = _get_value,
+ .get_noskip_flag = _get_noskip_flag,
+ .set_noskip_flag = _set_noskip_flag,
+ .build = _build,
+ .process = _process,
+ .add_segment = _add_segment,
+ .get_ref = _get_ref,
+ .destroy = _destroy,
+ },
+ .get_vendor_smi_code = _get_vendor_smi_code,
+ },
+ .type = { PEN_PWG, PWG_HCD_VENDOR_SMI_CODE },
+ .length = length,
+ .value = chunk_clone(data),
+ .ref = 1,
+ );
+
+ return &this->public.pa_tnc_attribute;
+}
+
diff --git a/src/libimcv/pwg/pwg_attr_vendor_smi_code.h b/src/libimcv/pwg/pwg_attr_vendor_smi_code.h
new file mode 100644
index 000000000..31255b43f
--- /dev/null
+++ b/src/libimcv/pwg/pwg_attr_vendor_smi_code.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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 pwg_attr_vendor_smi_codet pwg_attr_vendor_smi_code
+ * @{ @ingroup ietf_attr
+ */
+
+#ifndef PWG_ATTR_VENDOR_SMI_CODE_H_
+#define PWG_ATTR_VENDOR_SMI_CODE_H_
+
+typedef struct pwg_attr_vendor_smi_code_t pwg_attr_vendor_smi_code_t;
+
+#include "pwg_attr.h"
+#include "pa_tnc/pa_tnc_attr.h"
+
+
+/**
+ * Class implementing the PWG HCD PA-TNC Vendor SMI Code attribute.
+ *
+ */
+struct pwg_attr_vendor_smi_code_t {
+
+ /**
+ * Public PA-TNC attribute interface
+ */
+ pa_tnc_attr_t pa_tnc_attribute;
+
+ /**
+ * Gets the Vendor SMI Code
+ *
+ * @return Vendor SMI Code
+ */
+ pen_t (*get_vendor_smi_code)(pwg_attr_vendor_smi_code_t *this);
+
+};
+
+/**
+ * Creates an pwg_attr_vendor_smi_code_t object
+ *
+ */
+pa_tnc_attr_t* pwg_attr_vendor_smi_code_create(pen_t vendor_smi_code);
+
+/**
+ * Creates an pwg_attr_vendor_smi_code_t object from received data
+ *
+ * @param length Total length of attribute value
+ * @param value Unparsed attribute value (might be a segment)
+ */
+pa_tnc_attr_t* pwg_attr_vendor_smi_code_create_from_data(size_t length,
+ chunk_t value);
+
+#endif /** PWG_ATTR_VENDOR_SMI_CODE_H_ @}*/
diff --git a/src/libimcv/seg/seg_contract.c b/src/libimcv/seg/seg_contract.c
index 7db702a08..41aed583a 100644
--- a/src/libimcv/seg/seg_contract.c
+++ b/src/libimcv/seg/seg_contract.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Andreas Steffen
+ * Copyright (C) 2014-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -148,7 +148,7 @@ METHOD(seg_contract_t, check_size, bool,
}
METHOD(seg_contract_t, first_segment, pa_tnc_attr_t*,
- private_seg_contract_t *this, pa_tnc_attr_t *attr)
+ private_seg_contract_t *this, pa_tnc_attr_t *attr, size_t max_attr_len)
{
seg_env_t *seg_env;
@@ -160,7 +160,7 @@ METHOD(seg_contract_t, first_segment, pa_tnc_attr_t*,
}
this->seg_envs->insert_last(this->seg_envs, seg_env);
- return seg_env->first_segment(seg_env);
+ return seg_env->first_segment(seg_env, max_attr_len);
}
METHOD(seg_contract_t, next_segment, pa_tnc_attr_t*,
diff --git a/src/libimcv/seg/seg_contract.h b/src/libimcv/seg/seg_contract.h
index 23676a9f4..afbf30934 100644
--- a/src/libimcv/seg/seg_contract.h
+++ b/src/libimcv/seg/seg_contract.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Andreas Steffen
+ * Copyright (C) 2014-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -78,9 +78,11 @@ struct seg_contract_t {
* Generate first segment of a PA-TNC attribute according to the contract
*
* @param attr PA-TNC attribute to be segmented
+ * @param max_attr_len Maximum size of first segment envelope attribute
* @return First segment envelope attribute
*/
- pa_tnc_attr_t* (*first_segment)(seg_contract_t *this, pa_tnc_attr_t *attr);
+ pa_tnc_attr_t* (*first_segment)(seg_contract_t *this, pa_tnc_attr_t *attr,
+ size_t max_attr_len);
/**
* Generate next segment of a PA-TNC attribute according to the contract
diff --git a/src/libimcv/seg/seg_env.c b/src/libimcv/seg/seg_env.c
index f38419248..8d0f76007 100644
--- a/src/libimcv/seg/seg_env.c
+++ b/src/libimcv/seg/seg_env.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Andreas Steffen
+ * Copyright (C) 2014-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -89,14 +89,21 @@ METHOD(seg_env_t, get_base_attr_info, chunk_t,
}
METHOD(seg_env_t, first_segment, pa_tnc_attr_t*,
- private_seg_env_t *this)
+ private_seg_env_t *this, size_t max_attr_len)
{
pa_tnc_attr_t *seg_env_attr;
bio_writer_t *writer;
pen_type_t type;
chunk_t segment_data, value;
+ size_t seg_size;
uint8_t flags, seg_env_flags;
+ /* compute size of first segment */
+ seg_size = max_attr_len ? min(this->max_seg_size,
+ max_attr_len - PA_TNC_ATTR_HEADER_SIZE
+ - TCG_SEG_ATTR_SEG_ENV_HEADER)
+ : this->max_seg_size;
+
/* get components of base attribute header and data */
flags = this->base_attr->get_noskip_flag(this->base_attr) ?
PA_TNC_ATTR_FLAG_NOSKIP : PA_TNC_ATTR_FLAG_NONE;
@@ -104,7 +111,7 @@ METHOD(seg_env_t, first_segment, pa_tnc_attr_t*,
/* attribute data going into the first segment */
segment_data = this->data;
- segment_data.len = this->max_seg_size - PA_TNC_ATTR_HEADER_SIZE;
+ segment_data.len = seg_size - PA_TNC_ATTR_HEADER_SIZE;
/* build encoding of the base attribute header and first segment data */
writer = bio_writer_create(this->max_seg_size);
@@ -118,7 +125,7 @@ METHOD(seg_env_t, first_segment, pa_tnc_attr_t*,
this->data = chunk_skip(this->data, segment_data.len);
DBG2(DBG_TNC, "creating first segment for base attribute ID %d (%d bytes)",
- this->base_attr_id, this->max_seg_size);
+ this->base_attr_id, seg_size);
seg_env_flags = SEG_ENV_FLAG_START | SEG_ENV_FLAG_MORE;
seg_env_attr = tcg_seg_attr_seg_env_create(value, seg_env_flags,
diff --git a/src/libimcv/seg/seg_env.h b/src/libimcv/seg/seg_env.h
index 611f9a98a..5f21236f0 100644
--- a/src/libimcv/seg/seg_env.h
+++ b/src/libimcv/seg/seg_env.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 Andreas Steffen
+ * Copyright (C) 2014-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -66,9 +66,10 @@ struct seg_env_t {
/**
* Generate the first segment envelope of the base attribute
*
+ * @param max_attr_len Maximum size of first attribute segment envelope
* @return First attribute segment envelope
*/
- pa_tnc_attr_t* (*first_segment)(seg_env_t *this);
+ pa_tnc_attr_t* (*first_segment)(seg_env_t *this, size_t max_attr_len);
/**
* Generate the next segment envelope of the base attribute
diff --git a/src/libimcv/suites/test_imcv_seg.c b/src/libimcv/suites/test_imcv_seg.c
index 8b51eda05..5245be9fa 100644
--- a/src/libimcv/suites/test_imcv_seg.c
+++ b/src/libimcv/suites/test_imcv_seg.c
@@ -42,7 +42,7 @@ static struct {
{ 24, 1, 24 },
{ 25, 1, 23 },
{ 47, 1, 1 },
- { 48, 0, 0 },
+ { 48, 0, 0 },
};
static char command[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
@@ -87,7 +87,7 @@ START_TEST(test_imcv_seg_env)
if (n == 0)
{
/* create first segment */
- attr = seg_env->first_segment(seg_env);
+ attr = seg_env->first_segment(seg_env, 0);
seg_env_attr = (tcg_seg_attr_seg_env_t*)attr;
segment = seg_env_attr->get_segment(seg_env_attr, &flags);
@@ -168,8 +168,9 @@ START_TEST(test_imcv_seg_env_special)
pen_type_t type;
seg_env_t *seg_env;
chunk_t segment, value;
+ uint32_t max_attr_len = 60;
uint32_t max_seg_size = 47;
- uint32_t last_seg_size = 1;
+ uint32_t last_seg_size = 4;
uint32_t offset = 12;
base_attr = ita_attr_command_create(command);
@@ -179,7 +180,7 @@ START_TEST(test_imcv_seg_env_special)
base_attr->set_noskip_flag(base_attr, TRUE);
seg_env = seg_env_create(id, base_attr, max_seg_size);
- attr = seg_env->first_segment(seg_env);
+ attr = seg_env->first_segment(seg_env, max_attr_len);
attr->destroy(attr);
/* don't return last segment indicator */
@@ -306,7 +307,7 @@ START_TEST(test_imcv_seg_contract)
contract_r = seg_contract_create(msg_type, max_attr_size, max_seg_size,
FALSE, issuer_id, TRUE);
attr = contract_r->first_segment(contract_r,
- base_attr_r->get_ref(base_attr_r));
+ base_attr_r->get_ref(base_attr_r), 0);
if (seg_env_tests[_i].next_segs == 0)
{
@@ -422,8 +423,8 @@ START_TEST(test_imcv_seg_contract_special)
ck_assert(!oversize);
/* get first segment of each base attribute */
- attr1_f = contract_r->first_segment(contract_r, base_attr1_r->get_ref(base_attr1_r));
- attr2_f = contract_r->first_segment(contract_r, base_attr2_r->get_ref(base_attr2_r));
+ attr1_f = contract_r->first_segment(contract_r, base_attr1_r->get_ref(base_attr1_r), 0);
+ attr2_f = contract_r->first_segment(contract_r, base_attr2_r->get_ref(base_attr2_r), 0);
ck_assert(attr1_f);
ck_assert(attr2_f);
seg_env_attr1 = (tcg_seg_attr_seg_env_t*)attr1_f;
diff --git a/src/libipsec/Makefile.am b/src/libipsec/Makefile.am
index 41f5ae937..90b456114 100644
--- a/src/libipsec/Makefile.am
+++ b/src/libipsec/Makefile.am
@@ -24,11 +24,4 @@ AM_LDFLAGS = \
EXTRA_DIST = Android.mk
-# build optional plugins
-########################
-
-if MONOLITHIC
-SUBDIRS =
-else
-SUBDIRS = .
-endif
+SUBDIRS = . tests
diff --git a/src/libipsec/Makefile.in b/src/libipsec/Makefile.in
index a80d28ac6..aa793441b 100644
--- a/src/libipsec/Makefile.in
+++ b/src/libipsec/Makefile.in
@@ -214,7 +214,7 @@ am__define_uniq_tagged_files = \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
-DIST_SUBDIRS = .
+DIST_SUBDIRS = $(SUBDIRS)
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -490,11 +490,7 @@ AM_LDFLAGS = \
-no-undefined
EXTRA_DIST = Android.mk
-@MONOLITHIC_FALSE@SUBDIRS = .
-
-# build optional plugins
-########################
-@MONOLITHIC_TRUE@SUBDIRS =
+SUBDIRS = . tests
all: all-recursive
.SUFFIXES:
diff --git a/src/libipsec/esp_context.c b/src/libipsec/esp_context.c
index a2307e048..b742d1576 100644
--- a/src/libipsec/esp_context.c
+++ b/src/libipsec/esp_context.c
@@ -215,6 +215,7 @@ static bool create_aead(private_esp_context_t *this, int alg,
case ENCR_AES_GCM_ICV8:
case ENCR_AES_GCM_ICV12:
case ENCR_AES_GCM_ICV16:
+ case ENCR_CHACHA20_POLY1305:
/* the key includes a 4 byte salt */
this->aead = lib->crypto->create_aead(lib->crypto, alg,
key.len - 4, 4);
diff --git a/src/libipsec/tests/Makefile.am b/src/libipsec/tests/Makefile.am
new file mode 100644
index 000000000..6138833e7
--- /dev/null
+++ b/src/libipsec/tests/Makefile.am
@@ -0,0 +1,21 @@
+TESTS = ipsec_tests
+
+check_PROGRAMS = $(TESTS)
+
+ipsec_tests_SOURCES = \
+ suites/test_chapoly.c \
+ ipsec_tests.h ipsec_tests.c
+
+ipsec_tests_CFLAGS = \
+ -I$(top_srcdir)/src/libipsec \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libstrongswan/tests \
+ -DPLUGINDIR=\""$(abs_top_builddir)/src/libstrongswan/plugins\"" \
+ -DPLUGINS=\""${s_plugins}\"" \
+ @COVERAGE_CFLAGS@
+
+ipsec_tests_LDFLAGS = @COVERAGE_LDFLAGS@
+ipsec_tests_LDADD = \
+ $(top_builddir)/src/libipsec/libipsec.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libstrongswan/tests/libtest.la
diff --git a/src/libipsec/tests/Makefile.in b/src/libipsec/tests/Makefile.in
new file mode 100644
index 000000000..9a9bb3142
--- /dev/null
+++ b/src/libipsec/tests/Makefile.in
@@ -0,0 +1,870 @@
+# Makefile.in generated by automake 1.14.1 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994-2013 Free Software Foundation, Inc.
+
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+VPATH = @srcdir@
+am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
+am__make_running_with_option = \
+ case $${target_option-} in \
+ ?) ;; \
+ *) echo "am__make_running_with_option: internal error: invalid" \
+ "target option '$${target_option-}' specified" >&2; \
+ exit 1;; \
+ esac; \
+ has_opt=no; \
+ sane_makeflags=$$MAKEFLAGS; \
+ if $(am__is_gnu_make); then \
+ sane_makeflags=$$MFLAGS; \
+ else \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ bs=\\; \
+ sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
+ | sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
+ esac; \
+ fi; \
+ skip_next=no; \
+ strip_trailopt () \
+ { \
+ flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
+ }; \
+ for flg in $$sane_makeflags; do \
+ test $$skip_next = yes && { skip_next=no; continue; }; \
+ case $$flg in \
+ *=*|--*) continue;; \
+ -*I) strip_trailopt 'I'; skip_next=yes;; \
+ -*I?*) strip_trailopt 'I';; \
+ -*O) strip_trailopt 'O'; skip_next=yes;; \
+ -*O?*) strip_trailopt 'O';; \
+ -*l) strip_trailopt 'l'; skip_next=yes;; \
+ -*l?*) strip_trailopt 'l';; \
+ -[dEDm]) skip_next=yes;; \
+ -[JT]) skip_next=yes;; \
+ esac; \
+ case $$flg in \
+ *$$target_option*) has_opt=yes; break;; \
+ esac; \
+ done; \
+ test $$has_opt = yes
+am__make_dryrun = (target_option=n; $(am__make_running_with_option))
+am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+TESTS = ipsec_tests$(EXEEXT)
+check_PROGRAMS = $(am__EXEEXT_1)
+subdir = src/libipsec/tests
+DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
+ $(top_srcdir)/depcomp
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
+ $(top_srcdir)/m4/config/ltoptions.m4 \
+ $(top_srcdir)/m4/config/ltsugar.m4 \
+ $(top_srcdir)/m4/config/ltversion.m4 \
+ $(top_srcdir)/m4/config/lt~obsolete.m4 \
+ $(top_srcdir)/m4/macros/split-package-version.m4 \
+ $(top_srcdir)/m4/macros/with.m4 \
+ $(top_srcdir)/m4/macros/enable-disable.m4 \
+ $(top_srcdir)/m4/macros/add-plugin.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(install_sh) -d
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+am__EXEEXT_1 = ipsec_tests$(EXEEXT)
+am__dirstamp = $(am__leading_dot)dirstamp
+am_ipsec_tests_OBJECTS = suites/ipsec_tests-test_chapoly.$(OBJEXT) \
+ ipsec_tests-ipsec_tests.$(OBJEXT)
+ipsec_tests_OBJECTS = $(am_ipsec_tests_OBJECTS)
+ipsec_tests_DEPENDENCIES = $(top_builddir)/src/libipsec/libipsec.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libstrongswan/tests/libtest.la
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+am__v_lt_1 =
+ipsec_tests_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(ipsec_tests_CFLAGS) \
+ $(CFLAGS) $(ipsec_tests_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_P = $(am__v_P_@AM_V@)
+am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
+am__v_P_0 = false
+am__v_P_1 = :
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+am__v_GEN_1 =
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+am__v_at_1 =
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+am__v_CC_1 =
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+am__v_CCLD_1 =
+SOURCES = $(ipsec_tests_SOURCES)
+DIST_SOURCES = $(ipsec_tests_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+am__tty_colors_dummy = \
+ mgn= red= grn= lgn= blu= brg= std=; \
+ am__color_tests=no
+am__tty_colors = { \
+ $(am__tty_colors_dummy); \
+ if test "X$(AM_COLOR_TESTS)" = Xno; then \
+ am__color_tests=no; \
+ elif test "X$(AM_COLOR_TESTS)" = Xalways; then \
+ am__color_tests=yes; \
+ elif test "X$$TERM" != Xdumb && { test -t 1; } 2>/dev/null; then \
+ am__color_tests=yes; \
+ fi; \
+ if test $$am__color_tests = yes; then \
+ red=''; \
+ grn=''; \
+ lgn=''; \
+ blu=''; \
+ mgn=''; \
+ brg=''; \
+ std=''; \
+ fi; \
+}
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+ipsec_tests_SOURCES = \
+ suites/test_chapoly.c \
+ ipsec_tests.h ipsec_tests.c
+
+ipsec_tests_CFLAGS = \
+ -I$(top_srcdir)/src/libipsec \
+ -I$(top_srcdir)/src/libstrongswan \
+ -I$(top_srcdir)/src/libstrongswan/tests \
+ -DPLUGINDIR=\""$(abs_top_builddir)/src/libstrongswan/plugins\"" \
+ -DPLUGINS=\""${s_plugins}\"" \
+ @COVERAGE_CFLAGS@
+
+ipsec_tests_LDFLAGS = @COVERAGE_LDFLAGS@
+ipsec_tests_LDADD = \
+ $(top_builddir)/src/libipsec/libipsec.la \
+ $(top_builddir)/src/libstrongswan/libstrongswan.la \
+ $(top_builddir)/src/libstrongswan/tests/libtest.la
+
+all: all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/libipsec/tests/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libipsec/tests/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-checkPROGRAMS:
+ @list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+suites/$(am__dirstamp):
+ @$(MKDIR_P) suites
+ @: > suites/$(am__dirstamp)
+suites/$(DEPDIR)/$(am__dirstamp):
+ @$(MKDIR_P) suites/$(DEPDIR)
+ @: > suites/$(DEPDIR)/$(am__dirstamp)
+suites/ipsec_tests-test_chapoly.$(OBJEXT): suites/$(am__dirstamp) \
+ suites/$(DEPDIR)/$(am__dirstamp)
+
+ipsec_tests$(EXEEXT): $(ipsec_tests_OBJECTS) $(ipsec_tests_DEPENDENCIES) $(EXTRA_ipsec_tests_DEPENDENCIES)
+ @rm -f ipsec_tests$(EXEEXT)
+ $(AM_V_CCLD)$(ipsec_tests_LINK) $(ipsec_tests_OBJECTS) $(ipsec_tests_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+ -rm -f suites/*.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ipsec_tests-ipsec_tests.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@suites/$(DEPDIR)/ipsec_tests-test_chapoly.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.o$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.obj$$||'`;\
+@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ `$(CYGPATH_W) '$<'` &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
+@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
+@am__fastdepCC_TRUE@ $(am__mv) $$depbase.Tpo $$depbase.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+suites/ipsec_tests-test_chapoly.o: suites/test_chapoly.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipsec_tests_CFLAGS) $(CFLAGS) -MT suites/ipsec_tests-test_chapoly.o -MD -MP -MF suites/$(DEPDIR)/ipsec_tests-test_chapoly.Tpo -c -o suites/ipsec_tests-test_chapoly.o `test -f 'suites/test_chapoly.c' || echo '$(srcdir)/'`suites/test_chapoly.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/ipsec_tests-test_chapoly.Tpo suites/$(DEPDIR)/ipsec_tests-test_chapoly.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_chapoly.c' object='suites/ipsec_tests-test_chapoly.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipsec_tests_CFLAGS) $(CFLAGS) -c -o suites/ipsec_tests-test_chapoly.o `test -f 'suites/test_chapoly.c' || echo '$(srcdir)/'`suites/test_chapoly.c
+
+suites/ipsec_tests-test_chapoly.obj: suites/test_chapoly.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipsec_tests_CFLAGS) $(CFLAGS) -MT suites/ipsec_tests-test_chapoly.obj -MD -MP -MF suites/$(DEPDIR)/ipsec_tests-test_chapoly.Tpo -c -o suites/ipsec_tests-test_chapoly.obj `if test -f 'suites/test_chapoly.c'; then $(CYGPATH_W) 'suites/test_chapoly.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_chapoly.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) suites/$(DEPDIR)/ipsec_tests-test_chapoly.Tpo suites/$(DEPDIR)/ipsec_tests-test_chapoly.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='suites/test_chapoly.c' object='suites/ipsec_tests-test_chapoly.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipsec_tests_CFLAGS) $(CFLAGS) -c -o suites/ipsec_tests-test_chapoly.obj `if test -f 'suites/test_chapoly.c'; then $(CYGPATH_W) 'suites/test_chapoly.c'; else $(CYGPATH_W) '$(srcdir)/suites/test_chapoly.c'; fi`
+
+ipsec_tests-ipsec_tests.o: ipsec_tests.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipsec_tests_CFLAGS) $(CFLAGS) -MT ipsec_tests-ipsec_tests.o -MD -MP -MF $(DEPDIR)/ipsec_tests-ipsec_tests.Tpo -c -o ipsec_tests-ipsec_tests.o `test -f 'ipsec_tests.c' || echo '$(srcdir)/'`ipsec_tests.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipsec_tests-ipsec_tests.Tpo $(DEPDIR)/ipsec_tests-ipsec_tests.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ipsec_tests.c' object='ipsec_tests-ipsec_tests.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipsec_tests_CFLAGS) $(CFLAGS) -c -o ipsec_tests-ipsec_tests.o `test -f 'ipsec_tests.c' || echo '$(srcdir)/'`ipsec_tests.c
+
+ipsec_tests-ipsec_tests.obj: ipsec_tests.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipsec_tests_CFLAGS) $(CFLAGS) -MT ipsec_tests-ipsec_tests.obj -MD -MP -MF $(DEPDIR)/ipsec_tests-ipsec_tests.Tpo -c -o ipsec_tests-ipsec_tests.obj `if test -f 'ipsec_tests.c'; then $(CYGPATH_W) 'ipsec_tests.c'; else $(CYGPATH_W) '$(srcdir)/ipsec_tests.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/ipsec_tests-ipsec_tests.Tpo $(DEPDIR)/ipsec_tests-ipsec_tests.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ipsec_tests.c' object='ipsec_tests-ipsec_tests.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ipsec_tests_CFLAGS) $(CFLAGS) -c -o ipsec_tests-ipsec_tests.obj `if test -f 'ipsec_tests.c'; then $(CYGPATH_W) 'ipsec_tests.c'; else $(CYGPATH_W) '$(srcdir)/ipsec_tests.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(am__tagged_files)
+ $(am__define_uniq_tagged_files); mkid -fID $$unique
+tags: tags-am
+TAGS: tags
+
+tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ set x; \
+ here=`pwd`; \
+ $(am__define_uniq_tagged_files); \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: ctags-am
+
+CTAGS: ctags
+ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
+ $(am__define_uniq_tagged_files); \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+cscopelist: cscopelist-am
+
+cscopelist-am: $(am__tagged_files)
+ list='$(am__tagged_files)'; \
+ case "$(srcdir)" in \
+ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
+ *) sdir=$(subdir)/$(srcdir) ;; \
+ esac; \
+ for i in $$list; do \
+ if test -f "$$i"; then \
+ echo "$(subdir)/$$i"; \
+ else \
+ echo "$$sdir/$$i"; \
+ fi; \
+ done >> $(top_builddir)/cscope.files
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+check-TESTS: $(TESTS)
+ @failed=0; all=0; xfail=0; xpass=0; skip=0; \
+ srcdir=$(srcdir); export srcdir; \
+ list=' $(TESTS) '; \
+ $(am__tty_colors); \
+ if test -n "$$list"; then \
+ for tst in $$list; do \
+ if test -f ./$$tst; then dir=./; \
+ elif test -f $$tst; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ if $(TESTS_ENVIRONMENT) $${dir}$$tst $(AM_TESTS_FD_REDIRECT); then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xpass=`expr $$xpass + 1`; \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=XPASS; \
+ ;; \
+ *) \
+ col=$$grn; res=PASS; \
+ ;; \
+ esac; \
+ elif test $$? -ne 77; then \
+ all=`expr $$all + 1`; \
+ case " $(XFAIL_TESTS) " in \
+ *[\ \ ]$$tst[\ \ ]*) \
+ xfail=`expr $$xfail + 1`; \
+ col=$$lgn; res=XFAIL; \
+ ;; \
+ *) \
+ failed=`expr $$failed + 1`; \
+ col=$$red; res=FAIL; \
+ ;; \
+ esac; \
+ else \
+ skip=`expr $$skip + 1`; \
+ col=$$blu; res=SKIP; \
+ fi; \
+ echo "$${col}$$res$${std}: $$tst"; \
+ done; \
+ if test "$$all" -eq 1; then \
+ tests="test"; \
+ All=""; \
+ else \
+ tests="tests"; \
+ All="All "; \
+ fi; \
+ if test "$$failed" -eq 0; then \
+ if test "$$xfail" -eq 0; then \
+ banner="$$All$$all $$tests passed"; \
+ else \
+ if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
+ banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
+ fi; \
+ else \
+ if test "$$xpass" -eq 0; then \
+ banner="$$failed of $$all $$tests failed"; \
+ else \
+ if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
+ banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
+ fi; \
+ fi; \
+ dashes="$$banner"; \
+ skipped=""; \
+ if test "$$skip" -ne 0; then \
+ if test "$$skip" -eq 1; then \
+ skipped="($$skip test was not run)"; \
+ else \
+ skipped="($$skip tests were not run)"; \
+ fi; \
+ test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$skipped"; \
+ fi; \
+ report=""; \
+ if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
+ report="Please report to $(PACKAGE_BUGREPORT)"; \
+ test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
+ dashes="$$report"; \
+ fi; \
+ dashes=`echo "$$dashes" | sed s/./=/g`; \
+ if test "$$failed" -eq 0; then \
+ col="$$grn"; \
+ else \
+ col="$$red"; \
+ fi; \
+ echo "$${col}$$dashes$${std}"; \
+ echo "$${col}$$banner$${std}"; \
+ test -z "$$skipped" || echo "$${col}$$skipped$${std}"; \
+ test -z "$$report" || echo "$${col}$$report$${std}"; \
+ echo "$${col}$$dashes$${std}"; \
+ test "$$failed" -eq 0; \
+ else :; fi
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+ $(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
+ $(MAKE) $(AM_MAKEFLAGS) check-TESTS
+check: check-am
+all-am: Makefile
+installdirs:
+install: install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+ -rm -f suites/$(DEPDIR)/$(am__dirstamp)
+ -rm -f suites/$(am__dirstamp)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+clean: clean-am
+
+clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
+ mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR) suites/$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am:
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR) suites/$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am:
+
+.MAKE: check-am install-am install-strip
+
+.PHONY: CTAGS GTAGS TAGS all all-am check check-TESTS check-am clean \
+ clean-checkPROGRAMS clean-generic clean-libtool cscopelist-am \
+ ctags ctags-am distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-ps install-ps-am install-strip installcheck \
+ installcheck-am installdirs maintainer-clean \
+ maintainer-clean-generic mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+ tags tags-am uninstall uninstall-am
+
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/libipsec/tests/ipsec_tests.c b/src/libipsec/tests/ipsec_tests.c
new file mode 100644
index 000000000..d5e905304
--- /dev/null
+++ b/src/libipsec/tests/ipsec_tests.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <test_runner.h>
+
+/* declare test suite constructors */
+#define TEST_SUITE(x) test_suite_t* x();
+#define TEST_SUITE_DEPEND(x, ...) TEST_SUITE(x)
+#include "ipsec_tests.h"
+#undef TEST_SUITE
+#undef TEST_SUITE_DEPEND
+
+static test_configuration_t tests[] = {
+#define TEST_SUITE(x) \
+ { .suite = x, },
+#define TEST_SUITE_DEPEND(x, type, ...) \
+ { .suite = x, .feature = PLUGIN_DEPENDS(type, __VA_ARGS__) },
+#include "ipsec_tests.h"
+ { .suite = NULL, }
+};
+
+static bool test_runner_init(bool init)
+{
+ if (init)
+ {
+ plugin_loader_add_plugindirs(PLUGINDIR, PLUGINS);
+ if (!lib->plugins->load(lib->plugins, PLUGINS))
+ {
+ return FALSE;
+ }
+ }
+ else
+ {
+ lib->credmgr->flush_cache(lib->credmgr, CERT_ANY);
+ lib->processor->set_threads(lib->processor, 0);
+ lib->processor->cancel(lib->processor);
+ lib->plugins->unload(lib->plugins);
+ }
+ return TRUE;
+}
+
+int main(int argc, char *argv[])
+{
+ return test_runner_run("libipsec", tests, test_runner_init);
+}
diff --git a/src/libipsec/tests/ipsec_tests.h b/src/libipsec/tests/ipsec_tests.h
new file mode 100644
index 000000000..1b591f9d0
--- /dev/null
+++ b/src/libipsec/tests/ipsec_tests.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+TEST_SUITE_DEPEND(chapoly_suite_create, AEAD, ENCR_CHACHA20_POLY1305, 32)
diff --git a/src/libipsec/tests/suites/test_chapoly.c b/src/libipsec/tests/suites/test_chapoly.c
new file mode 100644
index 000000000..31dc2ac7b
--- /dev/null
+++ b/src/libipsec/tests/suites/test_chapoly.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <test_suite.h>
+
+#include <ip_packet.h>
+#include <esp_packet.h>
+
+static iv_gen_t *ivgen;
+
+METHOD(aead_t, get_iv_gen, iv_gen_t*,
+ aead_t *this)
+{
+ return ivgen;
+}
+
+METHOD(iv_gen_t, get_iv, bool,
+ iv_gen_t *this, u_int64_t seq, size_t size, u_int8_t *buffer)
+{
+ if (size != 8)
+ {
+ return FALSE;
+ }
+ memcpy(buffer, "\x10\x11\x12\x13\x14\x15\x16\x17", 8);
+ return TRUE;
+}
+
+METHOD(iv_gen_t, allocate_iv, bool,
+ iv_gen_t *this, u_int64_t seq, size_t size, chunk_t *chunk)
+{
+ if (size != 8)
+ {
+ return FALSE;
+ }
+ *chunk = chunk_alloc(size);
+ return get_iv(this, seq, chunk->len, chunk->ptr);
+}
+
+/**
+ * Appendix A draft-ietf-ipsecme-chacha20-poly1305-06
+ */
+START_TEST(test_chapoly)
+{
+ host_t *src, *dst;
+ ip_packet_t *icmp;
+ esp_packet_t *esp;
+ esp_context_t *ctx;
+ chunk_t data, exp;
+ u_int32_t seq = 0;
+
+ icmp = ip_packet_create(chunk_clone(chunk_from_chars(
+ 0x45,0x00,0x00,0x54,0xa6,0xf2,0x00,0x00,
+ 0x40,0x01,0xe7,0x78,0xc6,0x33,0x64,0x05,
+ 0xc0,0x00,0x02,0x05,0x08,0x00,0x5b,0x7a,
+ 0x3a,0x08,0x00,0x00,0x55,0x3b,0xec,0x10,
+ 0x00,0x07,0x36,0x27,0x08,0x09,0x0a,0x0b,
+ 0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,
+ 0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,
+ 0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,
+ 0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,
+ 0x2c,0x2d,0x2e,0x2f,0x30,0x31,0x32,0x33,
+ 0x34,0x35,0x36,0x37)));
+ ck_assert(icmp);
+
+ src = host_create_from_string("203.0.113.153", 0);
+ dst = host_create_from_string("203.0.113.5", 0);
+ esp = esp_packet_create_from_payload(src, dst, icmp);
+
+ ctx = esp_context_create(ENCR_CHACHA20_POLY1305, chunk_from_chars(
+ 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,
+ 0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
+ 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,
+ 0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
+ 0xa0,0xa1,0xa2,0xa3),
+ AUTH_UNDEFINED, chunk_empty, FALSE);
+ while (seq != 4)
+ {
+ ck_assert(ctx->next_seqno(ctx, &seq));
+ }
+ INIT(ivgen,
+ .get_iv = _get_iv,
+ .allocate_iv = _allocate_iv,
+ .destroy = (void*)free,
+ );
+ ctx->get_aead(ctx)->get_iv_gen = _get_iv_gen;
+ ck_assert(esp->encrypt(esp, ctx, htonl(0x01020304)) == SUCCESS);
+
+ data = esp->packet.get_data(&esp->packet);
+ exp = chunk_from_chars(0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x05,
+ 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,
+ 0x24,0x03,0x94,0x28,0xb9,0x7f,0x41,0x7e,
+ 0x3c,0x13,0x75,0x3a,0x4f,0x05,0x08,0x7b,
+ 0x67,0xc3,0x52,0xe6,0xa7,0xfa,0xb1,0xb9,
+ 0x82,0xd4,0x66,0xef,0x40,0x7a,0xe5,0xc6,
+ 0x14,0xee,0x80,0x99,0xd5,0x28,0x44,0xeb,
+ 0x61,0xaa,0x95,0xdf,0xab,0x4c,0x02,0xf7,
+ 0x2a,0xa7,0x1e,0x7c,0x4c,0x4f,0x64,0xc9,
+ 0xbe,0xfe,0x2f,0xac,0xc6,0x38,0xe8,0xf3,
+ 0xcb,0xec,0x16,0x3f,0xac,0x46,0x9b,0x50,
+ 0x27,0x73,0xf6,0xfb,0x94,0xe6,0x64,0xda,
+ 0x91,0x65,0xb8,0x28,0x29,0xf6,0x41,0xe0,
+ 0x76,0xAA,0xA8,0x26,0x6B,0x7F,0xB0,0xF7,
+ 0xB1,0x1B,0x36,0x99,0x07,0xE1,0xAD,0x43);
+ ck_assert_msg(chunk_equals(data, exp), "got %B\nexp %B", &data, &exp);
+
+ esp->destroy(esp);
+ ctx->destroy(ctx);
+ ivgen->destroy(ivgen);
+}
+END_TEST
+
+Suite *chapoly_suite_create()
+{
+ Suite *s;
+ TCase *tc;
+
+ s = suite_create("chapoly");
+
+ tc = tcase_create("ChaCha20Poly1305 ESP encryption");
+ tcase_add_test(tc, test_chapoly);
+ suite_add_tcase(s, tc);
+
+ return s;
+}
diff --git a/src/libpttls/pt_tls_client.c b/src/libpttls/pt_tls_client.c
index 315129d7e..bd5b96f70 100644
--- a/src/libpttls/pt_tls_client.c
+++ b/src/libpttls/pt_tls_client.c
@@ -450,6 +450,7 @@ METHOD(pt_tls_client_t, run_assessment, status_t,
{
return FAILED;
}
+ tnccs->set_auth_type(tnccs, TNC_AUTH_X509_CERT);
DBG1(DBG_TNC, "entering PT-TLS data transport phase");
if (!assess(this, (tls_t*)tnccs))
diff --git a/src/libradius/radius_message.c b/src/libradius/radius_message.c
index e6abfe2c2..01c829841 100644
--- a/src/libradius/radius_message.c
+++ b/src/libradius/radius_message.c
@@ -97,7 +97,7 @@ ENUM_NEXT(radius_message_code_names, RMC_DISCONNECT_REQUEST, RMC_COA_NAK, RMC_AC
"CoA-NAK");
ENUM_END(radius_message_code_names, RMC_COA_NAK);
-ENUM(radius_attribute_type_names, RAT_USER_NAME, RAT_MIP6_HOME_LINK_PREFIX,
+ENUM_BEGIN(radius_attribute_type_names, RAT_USER_NAME, RAT_MIP6_HOME_LINK_PREFIX,
"User-Name",
"User-Password",
"CHAP-Password",
@@ -223,6 +223,13 @@ ENUM(radius_attribute_type_names, RAT_USER_NAME, RAT_MIP6_HOME_LINK_PREFIX,
"Delegated-IPv6-Prefix",
"MIP6-Feature-Vector",
"MIP6-Home-Link-Prefix");
+ENUM_NEXT(radius_attribute_type_names, RAT_FRAMED_IPV6_ADDRESS, RAT_STATEFUL_IPV6_ADDRESS_POOL, RAT_MIP6_HOME_LINK_PREFIX,
+ "Framed-IPv6-Address",
+ "DNS-Server-IPv6-Address",
+ "Route-IPv6-Information",
+ "Delegated-IPv6-Prefix-Pool",
+ "Stateful-IPv6-Address-Pool");
+ENUM_END(radius_attribute_type_names, RAT_STATEFUL_IPV6_ADDRESS_POOL);
/**
* Attribute enumerator implementation
diff --git a/src/libradius/radius_message.h b/src/libradius/radius_message.h
index 4ce03a44e..e6cb40b18 100644
--- a/src/libradius/radius_message.h
+++ b/src/libradius/radius_message.h
@@ -186,6 +186,11 @@ enum radius_attribute_type_t {
RAT_DELEGATED_IPV6_PREFIX = 123,
RAT_MIP6_FEATURE_VECTOR = 124,
RAT_MIP6_HOME_LINK_PREFIX = 125,
+ RAT_FRAMED_IPV6_ADDRESS = 168,
+ RAT_FRAMED_IPV6_DNS_SERVER = 169,
+ RAT_ROUTE_IPV6_INFORMATION = 170,
+ RAT_DELEGATED_IPV6_PREFIX_POOL = 171,
+ RAT_STATEFUL_IPV6_ADDRESS_POOL = 172,
};
/**
diff --git a/src/libstrongswan/Makefile.am b/src/libstrongswan/Makefile.am
index b3636cfb8..adf3687ae 100644
--- a/src/libstrongswan/Makefile.am
+++ b/src/libstrongswan/Makefile.am
@@ -100,7 +100,7 @@ resolver/rr.h resolver/resolver_manager.h \
plugins/plugin_loader.h plugins/plugin.h plugins/plugin_feature.h \
processing/jobs/job.h processing/jobs/callback_job.h processing/processor.h \
processing/scheduler.h processing/watcher.h selectors/traffic_selector.h \
-settings/settings.h threading/thread_value.h \
+settings/settings.h settings/settings_parser.h threading/thread_value.h \
threading/thread.h threading/windows/thread.h \
threading/mutex.h threading/condvar.h threading/spinlock.h threading/semaphore.h \
threading/rwlock.h threading/rwlock_condvar.h threading/lock_profiler.h \
@@ -540,6 +540,13 @@ if MONOLITHIC
endif
endif
+if USE_CHAPOLY
+ SUBDIRS += plugins/chapoly
+if MONOLITHIC
+ libstrongswan_la_LIBADD += plugins/chapoly/libstrongswan-chapoly.la
+endif
+endif
+
if USE_CTR
SUBDIRS += plugins/ctr
if MONOLITHIC
diff --git a/src/libstrongswan/Makefile.in b/src/libstrongswan/Makefile.in
index 5b20f6ea6..9598c8b51 100644
--- a/src/libstrongswan/Makefile.in
+++ b/src/libstrongswan/Makefile.in
@@ -203,19 +203,21 @@ host_triplet = @host@
@MONOLITHIC_TRUE@@USE_KEYCHAIN_TRUE@am__append_105 = plugins/keychain/libstrongswan-keychain.la
@USE_PKCS11_TRUE@am__append_106 = plugins/pkcs11
@MONOLITHIC_TRUE@@USE_PKCS11_TRUE@am__append_107 = plugins/pkcs11/libstrongswan-pkcs11.la
-@USE_CTR_TRUE@am__append_108 = plugins/ctr
-@MONOLITHIC_TRUE@@USE_CTR_TRUE@am__append_109 = plugins/ctr/libstrongswan-ctr.la
-@USE_CCM_TRUE@am__append_110 = plugins/ccm
-@MONOLITHIC_TRUE@@USE_CCM_TRUE@am__append_111 = plugins/ccm/libstrongswan-ccm.la
-@USE_GCM_TRUE@am__append_112 = plugins/gcm
-@MONOLITHIC_TRUE@@USE_GCM_TRUE@am__append_113 = plugins/gcm/libstrongswan-gcm.la
-@USE_NTRU_TRUE@am__append_114 = plugins/ntru
-@MONOLITHIC_TRUE@@USE_NTRU_TRUE@am__append_115 = plugins/ntru/libstrongswan-ntru.la
-@USE_BLISS_TRUE@am__append_116 = plugins/bliss
-@MONOLITHIC_TRUE@@USE_BLISS_TRUE@am__append_117 = plugins/bliss/libstrongswan-bliss.la
-@USE_TEST_VECTORS_TRUE@am__append_118 = plugins/test_vectors
-@MONOLITHIC_TRUE@@USE_TEST_VECTORS_TRUE@am__append_119 = plugins/test_vectors/libstrongswan-test-vectors.la
-@USE_BLISS_TRUE@am__append_120 = plugins/bliss/tests
+@USE_CHAPOLY_TRUE@am__append_108 = plugins/chapoly
+@MONOLITHIC_TRUE@@USE_CHAPOLY_TRUE@am__append_109 = plugins/chapoly/libstrongswan-chapoly.la
+@USE_CTR_TRUE@am__append_110 = plugins/ctr
+@MONOLITHIC_TRUE@@USE_CTR_TRUE@am__append_111 = plugins/ctr/libstrongswan-ctr.la
+@USE_CCM_TRUE@am__append_112 = plugins/ccm
+@MONOLITHIC_TRUE@@USE_CCM_TRUE@am__append_113 = plugins/ccm/libstrongswan-ccm.la
+@USE_GCM_TRUE@am__append_114 = plugins/gcm
+@MONOLITHIC_TRUE@@USE_GCM_TRUE@am__append_115 = plugins/gcm/libstrongswan-gcm.la
+@USE_NTRU_TRUE@am__append_116 = plugins/ntru
+@MONOLITHIC_TRUE@@USE_NTRU_TRUE@am__append_117 = plugins/ntru/libstrongswan-ntru.la
+@USE_BLISS_TRUE@am__append_118 = plugins/bliss
+@MONOLITHIC_TRUE@@USE_BLISS_TRUE@am__append_119 = plugins/bliss/libstrongswan-bliss.la
+@USE_TEST_VECTORS_TRUE@am__append_120 = plugins/test_vectors
+@MONOLITHIC_TRUE@@USE_TEST_VECTORS_TRUE@am__append_121 = plugins/test_vectors/libstrongswan-test-vectors.la
+@USE_BLISS_TRUE@am__append_122 = plugins/bliss/tests
subdir = src/libstrongswan
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
settings/settings_parser.h settings/settings_parser.c \
@@ -295,7 +297,7 @@ libstrongswan_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
$(am__append_101) $(am__append_103) $(am__append_105) \
$(am__append_107) $(am__append_109) $(am__append_111) \
$(am__append_113) $(am__append_115) $(am__append_117) \
- $(am__append_119)
+ $(am__append_119) $(am__append_121)
am__libstrongswan_la_SOURCES_DIST = library.c asn1/asn1.c \
asn1/asn1_parser.c asn1/oid.c bio/bio_reader.c \
bio/bio_writer.c collections/blocking_queue.c \
@@ -558,15 +560,16 @@ am__nobase_strongswan_include_HEADERS_DIST = library.h asn1/asn1.h \
processing/jobs/job.h processing/jobs/callback_job.h \
processing/processor.h processing/scheduler.h \
processing/watcher.h selectors/traffic_selector.h \
- settings/settings.h threading/thread_value.h \
- threading/thread.h threading/windows/thread.h \
- threading/mutex.h threading/condvar.h threading/spinlock.h \
- threading/semaphore.h threading/rwlock.h \
- threading/rwlock_condvar.h threading/lock_profiler.h \
- utils/utils.h utils/chunk.h utils/debug.h utils/enum.h \
- utils/identification.h utils/lexparser.h utils/optionsfrom.h \
- utils/capabilities.h utils/backtrace.h utils/cpu_feature.h \
- utils/leak_detective.h utils/printf_hook/printf_hook.h \
+ settings/settings.h settings/settings_parser.h \
+ threading/thread_value.h threading/thread.h \
+ threading/windows/thread.h threading/mutex.h \
+ threading/condvar.h threading/spinlock.h threading/semaphore.h \
+ threading/rwlock.h threading/rwlock_condvar.h \
+ threading/lock_profiler.h utils/utils.h utils/chunk.h \
+ utils/debug.h utils/enum.h utils/identification.h \
+ utils/lexparser.h utils/optionsfrom.h utils/capabilities.h \
+ utils/backtrace.h utils/cpu_feature.h utils/leak_detective.h \
+ utils/printf_hook/printf_hook.h \
utils/printf_hook/printf_hook_vstr.h \
utils/printf_hook/printf_hook_builtin.h utils/parser_helper.h \
utils/test.h utils/integrity_checker.h utils/process.h \
@@ -615,9 +618,9 @@ DIST_SUBDIRS = . plugins/af_alg plugins/aes plugins/des \
plugins/files plugins/winhttp plugins/unbound plugins/soup \
plugins/ldap plugins/mysql plugins/sqlite plugins/padlock \
plugins/openssl plugins/gcrypt plugins/fips_prf plugins/agent \
- plugins/keychain plugins/pkcs11 plugins/ctr plugins/ccm \
- plugins/gcm plugins/ntru plugins/bliss plugins/test_vectors \
- tests plugins/bliss/tests
+ plugins/keychain plugins/pkcs11 plugins/chapoly plugins/ctr \
+ plugins/ccm plugins/gcm plugins/ntru plugins/bliss \
+ plugins/test_vectors tests plugins/bliss/tests
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
am__relativize = \
dir0=`pwd`; \
@@ -970,7 +973,7 @@ settings/settings_types.h
@USE_DEV_HEADERS_TRUE@plugins/plugin_loader.h plugins/plugin.h plugins/plugin_feature.h \
@USE_DEV_HEADERS_TRUE@processing/jobs/job.h processing/jobs/callback_job.h processing/processor.h \
@USE_DEV_HEADERS_TRUE@processing/scheduler.h processing/watcher.h selectors/traffic_selector.h \
-@USE_DEV_HEADERS_TRUE@settings/settings.h threading/thread_value.h \
+@USE_DEV_HEADERS_TRUE@settings/settings.h settings/settings_parser.h threading/thread_value.h \
@USE_DEV_HEADERS_TRUE@threading/thread.h threading/windows/thread.h \
@USE_DEV_HEADERS_TRUE@threading/mutex.h threading/condvar.h threading/spinlock.h threading/semaphore.h \
@USE_DEV_HEADERS_TRUE@threading/rwlock.h threading/rwlock_condvar.h threading/lock_profiler.h \
@@ -1004,7 +1007,7 @@ libstrongswan_la_LIBADD = $(DLLIB) $(BTLIB) $(SOCKLIB) $(RTLIB) \
$(am__append_101) $(am__append_103) $(am__append_105) \
$(am__append_107) $(am__append_109) $(am__append_111) \
$(am__append_113) $(am__append_115) $(am__append_117) \
- $(am__append_119)
+ $(am__append_119) $(am__append_121)
AM_CPPFLAGS = -I$(top_srcdir)/src/libstrongswan \
-DIPSEC_DIR=\"${ipsecdir}\" -DIPSEC_LIB_DIR=\"${ipseclibdir}\" \
-DPLUGINDIR=\"${plugindir}\" \
@@ -1056,7 +1059,8 @@ $(srcdir)/crypto/proposal/proposal_keywords_static.c
@MONOLITHIC_FALSE@ $(am__append_106) $(am__append_108) \
@MONOLITHIC_FALSE@ $(am__append_110) $(am__append_112) \
@MONOLITHIC_FALSE@ $(am__append_114) $(am__append_116) \
-@MONOLITHIC_FALSE@ $(am__append_118) tests $(am__append_120)
+@MONOLITHIC_FALSE@ $(am__append_118) $(am__append_120) tests \
+@MONOLITHIC_FALSE@ $(am__append_122)
# build plugins with their own Makefile
#######################################
@@ -1085,7 +1089,8 @@ $(srcdir)/crypto/proposal/proposal_keywords_static.c
@MONOLITHIC_TRUE@ $(am__append_106) $(am__append_108) \
@MONOLITHIC_TRUE@ $(am__append_110) $(am__append_112) \
@MONOLITHIC_TRUE@ $(am__append_114) $(am__append_116) \
-@MONOLITHIC_TRUE@ $(am__append_118) . tests $(am__append_120)
+@MONOLITHIC_TRUE@ $(am__append_118) $(am__append_120) . tests \
+@MONOLITHIC_TRUE@ $(am__append_122)
all: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) all-recursive
diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c
index 37b89c61b..628bb99e6 100644
--- a/src/libstrongswan/asn1/asn1.c
+++ b/src/libstrongswan/asn1/asn1.c
@@ -340,7 +340,7 @@ static const int days[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 33
static const int tm_leap_1970 = 477;
/**
- * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calender time
+ * Converts ASN.1 UTCTIME or GENERALIZEDTIME into calendar time
*/
time_t asn1_to_time(const chunk_t *utctime, asn1_t type)
{
diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c
index 0ca45a15b..1e93f021a 100644
--- a/src/libstrongswan/credentials/auth_cfg.c
+++ b/src/libstrongswan/credentials/auth_cfg.c
@@ -514,9 +514,10 @@ METHOD(auth_cfg_t, complies, bool,
private_auth_cfg_t *this, auth_cfg_t *constraints, bool log_error)
{
enumerator_t *e1, *e2;
- bool success = TRUE, group_match = FALSE, cert_match = FALSE;
+ bool success = TRUE, group_match = FALSE;
+ bool ca_match = FALSE, cert_match = FALSE;
identification_t *require_group = NULL;
- certificate_t *require_cert = NULL;
+ certificate_t *require_ca = NULL, *require_cert = NULL;
signature_scheme_t scheme = SIGN_UNKNOWN;
u_int strength = 0;
auth_rule_t t1, t2;
@@ -531,26 +532,21 @@ METHOD(auth_cfg_t, complies, bool,
case AUTH_RULE_CA_CERT:
case AUTH_RULE_IM_CERT:
{
- certificate_t *c1, *c2;
+ certificate_t *cert;
- c1 = (certificate_t*)value;
+ /* for CA certs, a match of a single cert is sufficient */
+ require_ca = (certificate_t*)value;
- success = FALSE;
e2 = create_enumerator(this);
- while (e2->enumerate(e2, &t2, &c2))
+ while (e2->enumerate(e2, &t2, &cert))
{
if ((t2 == AUTH_RULE_CA_CERT || t2 == AUTH_RULE_IM_CERT) &&
- c1->equals(c1, c2))
+ cert->equals(cert, require_ca))
{
- success = TRUE;
+ ca_match = TRUE;
}
}
e2->destroy(e2);
- if (!success && log_error)
- {
- DBG1(DBG_CFG, "constraint check failed: peer not "
- "authenticated by CA '%Y'.", c1->get_subject(c1));
- }
break;
}
case AUTH_RULE_SUBJECT_CERT:
@@ -665,7 +661,9 @@ METHOD(auth_cfg_t, complies, bool,
}
case AUTH_RULE_EAP_TYPE:
{
- if ((uintptr_t)value != (uintptr_t)get(this, t1))
+ if ((uintptr_t)value != (uintptr_t)get(this, t1) &&
+ (uintptr_t)value != EAP_DYNAMIC &&
+ (uintptr_t)value != EAP_RADIUS)
{
success = FALSE;
if (log_error)
@@ -853,13 +851,22 @@ METHOD(auth_cfg_t, complies, bool,
}
return FALSE;
}
-
+ if (require_ca && !ca_match)
+ {
+ if (log_error)
+ {
+ DBG1(DBG_CFG, "constraint check failed: peer not "
+ "authenticated by CA '%Y'",
+ require_ca->get_subject(require_ca));
+ }
+ return FALSE;
+ }
if (require_cert && !cert_match)
{
if (log_error)
{
DBG1(DBG_CFG, "constraint check failed: peer not "
- "authenticated with peer cert '%Y'.",
+ "authenticated with peer cert '%Y'",
require_cert->get_subject(require_cert));
}
return FALSE;
diff --git a/src/libstrongswan/credentials/certificates/ocsp_request.h b/src/libstrongswan/credentials/certificates/ocsp_request.h
index 0b1871309..730d95d70 100644
--- a/src/libstrongswan/credentials/certificates/ocsp_request.h
+++ b/src/libstrongswan/credentials/certificates/ocsp_request.h
@@ -31,7 +31,7 @@ typedef struct ocsp_request_t ocsp_request_t;
struct ocsp_request_t {
/**
- * Implements certificiate_t interface
+ * Implements certificate_t interface
*/
certificate_t interface;
};
diff --git a/src/libstrongswan/credentials/certificates/ocsp_response.h b/src/libstrongswan/credentials/certificates/ocsp_response.h
index 157577458..9c5637b9f 100644
--- a/src/libstrongswan/credentials/certificates/ocsp_response.h
+++ b/src/libstrongswan/credentials/certificates/ocsp_response.h
@@ -50,7 +50,7 @@ extern enum_name_t *ocsp_status_names;
struct ocsp_response_t {
/**
- * Implements certificiate_t interface
+ * Implements certificate_t interface
*/
certificate_t certificate;
diff --git a/src/libstrongswan/credentials/sets/mem_cred.c b/src/libstrongswan/credentials/sets/mem_cred.c
index 7ad011b5e..4884c4bfa 100644
--- a/src/libstrongswan/credentials/sets/mem_cred.c
+++ b/src/libstrongswan/credentials/sets/mem_cred.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 Tobias Brunner
+ * Copyright (C) 2010-2015 Tobias Brunner
* Hochschule fuer Technik Rapperwsil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
@@ -197,7 +197,7 @@ METHOD(mem_cred_t, get_cert_ref, certificate_t*,
{
certificate_t *cached;
- this->lock->write_lock(this->lock);
+ this->lock->read_lock(this->lock);
if (this->untrusted->find_first(this->untrusted,
(linked_list_match_t)certificate_equals,
(void**)&cached, cert) == SUCCESS)
@@ -643,6 +643,49 @@ METHOD(credential_set_t, create_cdp_enumerator, enumerator_t*,
}
+static void reset_certs(private_mem_cred_t *this)
+{
+ this->trusted->destroy_offset(this->trusted,
+ offsetof(certificate_t, destroy));
+ this->untrusted->destroy_offset(this->untrusted,
+ offsetof(certificate_t, destroy));
+ this->trusted = linked_list_create();
+ this->untrusted = linked_list_create();
+}
+
+static void copy_certs(linked_list_t *dst, linked_list_t *src, bool clone)
+{
+ enumerator_t *enumerator;
+ certificate_t *cert;
+
+ enumerator = src->create_enumerator(src);
+ while (enumerator->enumerate(enumerator, &cert))
+ {
+ if (clone)
+ {
+ cert = cert->get_ref(cert);
+ }
+ else
+ {
+ src->remove_at(src, enumerator);
+ }
+ dst->insert_last(dst, cert);
+ }
+ enumerator->destroy(enumerator);
+}
+
+METHOD(mem_cred_t, replace_certs, void,
+ private_mem_cred_t *this, mem_cred_t *other_set, bool clone)
+{
+ private_mem_cred_t *other = (private_mem_cred_t*)other_set;
+
+ this->lock->write_lock(this->lock);
+ reset_certs(this);
+ copy_certs(this->untrusted, other->untrusted, clone);
+ copy_certs(this->trusted, other->trusted, clone);
+ this->lock->unlock(this->lock);
+}
+
static void reset_secrets(private_mem_cred_t *this)
{
this->keys->destroy_offset(this->keys, offsetof(private_key_t, destroy));
@@ -710,17 +753,11 @@ METHOD(mem_cred_t, clear_, void,
private_mem_cred_t *this)
{
this->lock->write_lock(this->lock);
- this->trusted->destroy_offset(this->trusted,
- offsetof(certificate_t, destroy));
- this->untrusted->destroy_offset(this->untrusted,
- offsetof(certificate_t, destroy));
this->cdps->destroy_function(this->cdps, (void*)cdp_destroy);
- this->trusted = linked_list_create();
- this->untrusted = linked_list_create();
this->cdps = linked_list_create();
+ reset_certs(this);
+ reset_secrets(this);
this->lock->unlock(this->lock);
-
- clear_secrets(this);
}
METHOD(mem_cred_t, destroy, void,
@@ -760,6 +797,7 @@ mem_cred_t *mem_cred_create()
.add_shared = _add_shared,
.add_shared_list = _add_shared_list,
.add_cdp = _add_cdp,
+ .replace_certs = _replace_certs,
.replace_secrets = _replace_secrets,
.clear = _clear_,
.clear_secrets = _clear_secrets,
diff --git a/src/libstrongswan/credentials/sets/mem_cred.h b/src/libstrongswan/credentials/sets/mem_cred.h
index 3ce815abc..51f0b8c30 100644
--- a/src/libstrongswan/credentials/sets/mem_cred.h
+++ b/src/libstrongswan/credentials/sets/mem_cred.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 Tobias Brunner
+ * Copyright (C) 2010-2015 Tobias Brunner
* Hochschule fuer Technik Rapperswil
* Copyright (C) 2010 Martin Willi
* Copyright (C) 2010 revosec AG
@@ -102,6 +102,7 @@ struct mem_cred_t {
*/
void (*add_shared_list)(mem_cred_t *this, shared_key_t *shared,
linked_list_t *owners);
+
/**
* Add a certificate distribution point to the set.
*
@@ -113,6 +114,15 @@ struct mem_cred_t {
identification_t *id, char *uri);
/**
+ * Replace all certificates in this credential set with those of another.
+ *
+ * @param other credential set to get certificates from
+ * @param clone TRUE to clone certs, FALSE to adopt them (they
+ * get removed from the other set)
+ */
+ void (*replace_certs)(mem_cred_t *this, mem_cred_t *other, bool clone);
+
+ /**
* Replace all secrets (private and shared keys) in this credential set
* with those of another.
*
diff --git a/src/libstrongswan/crypto/crypters/crypter.c b/src/libstrongswan/crypto/crypters/crypter.c
index 1e73baa4e..3e33765b1 100644
--- a/src/libstrongswan/crypto/crypters/crypter.c
+++ b/src/libstrongswan/crypto/crypters/crypter.c
@@ -40,13 +40,14 @@ ENUM_NEXT(encryption_algorithm_names, ENCR_AES_GCM_ICV8, ENCR_NULL_AUTH_AES_GMAC
"AES_GCM_12",
"AES_GCM_16",
"NULL_AES_GMAC");
-ENUM_NEXT(encryption_algorithm_names, ENCR_CAMELLIA_CBC, ENCR_CAMELLIA_CCM_ICV16, ENCR_NULL_AUTH_AES_GMAC,
+ENUM_NEXT(encryption_algorithm_names, ENCR_CAMELLIA_CBC, ENCR_CHACHA20_POLY1305, ENCR_NULL_AUTH_AES_GMAC,
"CAMELLIA_CBC",
"CAMELLIA_CTR",
"CAMELLIA_CCM_8",
"CAMELLIA_CCM_12",
- "CAMELLIA_CCM_16");
-ENUM_NEXT(encryption_algorithm_names, ENCR_UNDEFINED, ENCR_RC2_CBC, ENCR_CAMELLIA_CCM_ICV16,
+ "CAMELLIA_CCM_16",
+ "CHACHA20_POLY1305");
+ENUM_NEXT(encryption_algorithm_names, ENCR_UNDEFINED, ENCR_RC2_CBC, ENCR_CHACHA20_POLY1305,
"UNDEFINED",
"DES_ECB",
"SERPENT_CBC",
@@ -184,6 +185,7 @@ bool encryption_algorithm_is_aead(encryption_algorithm_t alg)
case ENCR_CAMELLIA_CCM_ICV8:
case ENCR_CAMELLIA_CCM_ICV12:
case ENCR_CAMELLIA_CCM_ICV16:
+ case ENCR_CHACHA20_POLY1305:
return TRUE;
default:
return FALSE;
diff --git a/src/libstrongswan/crypto/crypters/crypter.h b/src/libstrongswan/crypto/crypters/crypter.h
index 849aea500..19ba55d83 100644
--- a/src/libstrongswan/crypto/crypters/crypter.h
+++ b/src/libstrongswan/crypto/crypters/crypter.h
@@ -57,6 +57,7 @@ enum encryption_algorithm_t {
ENCR_CAMELLIA_CCM_ICV8 = 25,
ENCR_CAMELLIA_CCM_ICV12 = 26,
ENCR_CAMELLIA_CCM_ICV16 = 27,
+ ENCR_CHACHA20_POLY1305 = 28,
ENCR_UNDEFINED = 1024,
ENCR_DES_ECB = 1025,
ENCR_SERPENT_CBC = 1026,
diff --git a/src/libstrongswan/crypto/iv/iv_gen.c b/src/libstrongswan/crypto/iv/iv_gen.c
index e18843210..7d6570a74 100644
--- a/src/libstrongswan/crypto/iv/iv_gen.c
+++ b/src/libstrongswan/crypto/iv/iv_gen.c
@@ -48,6 +48,7 @@ iv_gen_t* iv_gen_create_for_alg(encryption_algorithm_t alg)
case ENCR_CAMELLIA_CCM_ICV8:
case ENCR_CAMELLIA_CCM_ICV12:
case ENCR_CAMELLIA_CCM_ICV16:
+ case ENCR_CHACHA20_POLY1305:
case ENCR_NULL_AUTH_AES_GMAC:
return iv_gen_seq_create();
case ENCR_NULL:
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords_static.c b/src/libstrongswan/crypto/proposal/proposal_keywords_static.c
index 1da1421f4..51b9d782d 100644
--- a/src/libstrongswan/crypto/proposal/proposal_keywords_static.c
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords_static.c
@@ -59,12 +59,12 @@ struct proposal_token {
u_int16_t keysize;
};
-#define TOTAL_KEYWORDS 138
+#define TOTAL_KEYWORDS 139
#define MIN_WORD_LENGTH 3
#define MAX_WORD_LENGTH 17
-#define MIN_HASH_VALUE 20
-#define MAX_HASH_VALUE 295
-/* maximum key range = 276, duplicates = 0 */
+#define MIN_HASH_VALUE 18
+#define MAX_HASH_VALUE 276
+/* maximum key range = 259, duplicates = 0 */
#ifdef __GNUC__
__inline
@@ -80,32 +80,32 @@ hash (str, len)
{
static const unsigned short asso_values[] =
{
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 47, 6,
- 15, 8, 64, 24, 12, 14, 7, 5, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 120, 296, 9, 5, 22,
- 48, 114, 28, 76, 6, 5, 296, 296, 5, 20,
- 7, 14, 82, 7, 81, 98, 10, 86, 296, 296,
- 5, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296, 296, 296, 296,
- 296, 296, 296, 296, 296, 296, 296
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 66, 6,
+ 18, 39, 81, 30, 9, 27, 3, 0, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 105, 277, 33, 0, 6,
+ 57, 60, 15, 96, 3, 0, 277, 277, 0, 0,
+ 0, 18, 126, 30, 111, 24, 36, 159, 277, 277,
+ 9, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277, 277, 277, 277,
+ 277, 277, 277, 277, 277, 277, 277
};
register int hval = len;
@@ -144,178 +144,177 @@ hash (str, len)
static const struct proposal_token wordlist[] =
{
- {"sha1", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
- {"sha", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
+ {"esn", EXTENDED_SEQUENCE_NUMBERS, EXT_SEQ_NUMBERS, 0},
{"null", ENCRYPTION_ALGORITHM, ENCR_NULL, 0},
{"noesn", EXTENDED_SEQUENCE_NUMBERS, NO_EXT_SEQ_NUMBERS, 0},
- {"md5", INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0},
- {"esn", EXTENDED_SEQUENCE_NUMBERS, EXT_SEQ_NUMBERS, 0},
+ {"aesxcbc", INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0},
+ {"aes", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
{"aes128", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
- {"prfsha1", PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0},
- {"aes192", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192},
+ {"md5", INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0},
{"modp8192", DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0},
{"md5_128", INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_128, 0},
- {"sha512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
- {"modp768", DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0},
- {"ntru128", DIFFIE_HELLMAN_GROUP, NTRU_128_BIT, 0},
- {"prfsha256", PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_256, 0},
- {"aes256", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256},
- {"ecp521", DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0},
- {"ntru192", DIFFIE_HELLMAN_GROUP, NTRU_192_BIT, 0},
- {"ntru112", DIFFIE_HELLMAN_GROUP, NTRU_112_BIT, 0},
- {"sha256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
- {"modp1536", DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0},
- {"ecp192", DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0},
- {"prfsha512", PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_512, 0},
{"aes192ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
- {"aes192ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
+ {"aes192", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 192},
{"aes128ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
- {"aes128ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
{"aes192ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
- {"aes192ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
+ {"aes192ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
+ {"sha1", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
{"aes128ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
+ {"aes128ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
+ {"modp768", DIFFIE_HELLMAN_GROUP, MODP_768_BIT, 0},
+ {"aes192ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 192},
+ {"ecp521", DIFFIE_HELLMAN_GROUP, ECP_521_BIT, 0},
+ {"aescmac", INTEGRITY_ALGORITHM, AUTH_AES_CMAC_96, 0},
{"aes128ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 128},
+ {"aes256", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 256},
+ {"ntru128", DIFFIE_HELLMAN_GROUP, NTRU_128_BIT, 0},
+ {"blowfish", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
+ {"ecp192", DIFFIE_HELLMAN_GROUP, ECP_192_BIT, 0},
{"aes192ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 192},
- {"camellia", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
- {"aes128ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
- {"ecp256", DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0},
- {"aesxcbc", INTEGRITY_ALGORITHM, AUTH_AES_XCBC_96, 0},
- {"ntru256", DIFFIE_HELLMAN_GROUP, NTRU_256_BIT, 0},
- {"aescmac", INTEGRITY_ALGORITHM, AUTH_AES_CMAC_96, 0},
{"aes256ccm8", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
- {"aes256ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
- {"cast128", ENCRYPTION_ALGORITHM, ENCR_CAST, 128},
+ {"aes128ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 128},
{"aes256ccm96", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
+ {"aes256ccm128", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
+ {"ntru192", DIFFIE_HELLMAN_GROUP, NTRU_192_BIT, 0},
+ {"ecp256", DIFFIE_HELLMAN_GROUP, ECP_256_BIT, 0},
{"aes256ccm16", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV16, 256},
- {"camellia192", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 192},
- {"aes256ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
- {"camellia128", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
+ {"sha", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0},
+ {"ntru112", DIFFIE_HELLMAN_GROUP, NTRU_112_BIT, 0},
+ {"blowfish192", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192},
+ {"blowfish128", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
{"camellia192ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 192},
- {"camellia192ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 192},
- {"modp3072", DIFFIE_HELLMAN_GROUP, MODP_3072_BIT, 0},
+ {"aes256ccm12", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV12, 256},
+ {"camelliaxcbc", INTEGRITY_ALGORITHM, AUTH_CAMELLIA_XCBC_96, 0},
{"camellia192ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 192},
+ {"camellia192ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 192},
+ {"sha512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
+ {"prfsha1", PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0},
+ {"camellia192", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 192},
+ {"des", ENCRYPTION_ALGORITHM, ENCR_DES, 0},
{"camellia192ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 192},
- {"prfsha384", PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_384, 0},
- {"camellia192ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 192},
- {"aes", ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 128},
+ {"camellia128", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
+ {"sha256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
+ {"ntru256", DIFFIE_HELLMAN_GROUP, NTRU_256_BIT, 0},
+ {"modp1536", DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0},
+ {"cast128", ENCRYPTION_ALGORITHM, ENCR_CAST, 128},
+ {"blowfish256", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256},
{"camellia128ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 128},
- {"camellia128ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 128},
- {"prfmd5", PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0},
- {"camellia256", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 256},
+ {"camellia192ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 192},
+ {"camellia", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 128},
{"camellia128ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 128},
+ {"camellia128ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 128},
+ {"prfsha256", PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_256, 0},
{"camellia128ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 128},
- {"camellia128ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 128},
+ {"camellia256", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CBC, 256},
{"camellia256ccm8", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 256},
- {"camellia256ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 256},
- {"modpnull", DIFFIE_HELLMAN_GROUP, MODP_NULL, 0},
- {"camelliaxcbc", INTEGRITY_ALGORITHM, AUTH_CAMELLIA_XCBC_96, 0},
+ {"3des", ENCRYPTION_ALGORITHM, ENCR_3DES, 0},
{"camellia256ccm96", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 256},
+ {"camellia256ccm128",ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 256},
+ {"camellia128ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 128},
{"camellia256ccm16", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV16, 256},
+ {"prfsha512", PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_512, 0},
+ {"aes192ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
{"camellia256ccm12", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV12, 256},
+ {"aes128ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
{"aes192gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
- {"aes192gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
{"aes128gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
- {"aes128gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
{"aes192gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
- {"aes192gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
+ {"aes192gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
+ {"aes192gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 192},
{"aes128gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
+ {"aes128gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
+ {"aes128gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 128},
+ {"aes192gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 192},
+ {"prfaescmac", PSEUDO_RANDOM_FUNCTION, PRF_AES128_CMAC, 0},
{"aes128gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 128},
- {"aes192gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
- {"aes192ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 192},
- {"aes128gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
- {"aes128ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 128},
{"aes192ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 192},
+ {"prfaesxcbc", PSEUDO_RANDOM_FUNCTION, PRF_AES128_XCBC, 0},
+ {"aes256ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
{"aes128ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 128},
- {"modp1024s160", DIFFIE_HELLMAN_GROUP, MODP_1024_160, 0},
+ {"serpent128", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
+ {"aes192gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 192},
+ {"prfcamelliaxcbc", PSEUDO_RANDOM_FUNCTION, PRF_CAMELLIA128_XCBC, 0},
{"aes256gcm8", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
- {"aes256gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
- {"modp4096", DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0},
- {"ecp512bp", DIFFIE_HELLMAN_GROUP, ECP_512_BP, 0},
+ {"aes128gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 128},
+ {"prfmd5", PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0},
{"aes256gcm96", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
+ {"aes256gcm128", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
+ {"aes256gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 256},
+ {"modp3072", DIFFIE_HELLMAN_GROUP, MODP_3072_BIT, 0},
+ {"serpent256", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 256},
{"aes256gcm16", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256},
- {"modp1024", DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0},
- {"modp2048", DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0},
- {"aes256gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
- {"aes256ccm64", ENCRYPTION_ALGORITHM, ENCR_AES_CCM_ICV8, 256},
- {"sha384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0},
+ {"camellia192ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 192},
+ {"modp4096", DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0},
{"aes256ctr", ENCRYPTION_ALGORITHM, ENCR_AES_CTR, 256},
- {"aes192gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 192},
- {"aes128gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 128},
+ {"modpnull", DIFFIE_HELLMAN_GROUP, MODP_NULL, 0},
+ {"aes256gcm12", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV12, 256},
+ {"ecp512bp", DIFFIE_HELLMAN_GROUP, ECP_512_BP, 0},
+ {"modp1024s160", DIFFIE_HELLMAN_GROUP, MODP_1024_160, 0},
{"serpent", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
- {"ecp256bp", DIFFIE_HELLMAN_GROUP, ECP_256_BP, 0},
- {"camellia192ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 192},
- {"modp6144", DIFFIE_HELLMAN_GROUP, MODP_6144_BIT, 0},
+ {"modp2048", DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0},
+ {"serpent192", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 192},
+ {"modp1024", DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0},
+ {"camellia128ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 128},
{"camellia192ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 192},
- {"serpent128", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 128},
- {"3des", ENCRYPTION_ALGORITHM, ENCR_3DES, 0},
- {"blowfish", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
+ {"modp6144", DIFFIE_HELLMAN_GROUP, MODP_6144_BIT, 0},
{"ecp384", DIFFIE_HELLMAN_GROUP, ECP_384_BIT, 0},
- {"camellia128ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 128},
- {"aes256gmac", ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 256},
- {"modp2048s256", DIFFIE_HELLMAN_GROUP, MODP_2048_256, 0},
+ {"ecp256bp", DIFFIE_HELLMAN_GROUP, ECP_256_BP, 0},
+ {"camellia256ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 256},
+ {"prfsha384", PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA2_384, 0},
+ {"twofish", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
+ {"sha256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
{"camellia128ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 128},
- {"serpent256", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 256},
{"ecp224", DIFFIE_HELLMAN_GROUP, ECP_224_BIT, 0},
- {"camellia256ccm64", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CCM_ICV8, 256},
- {"serpent192", ENCRYPTION_ALGORITHM, ENCR_SERPENT_CBC, 192},
- {"camellia256ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 256},
+ {"twofish128", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
{"sha2_512", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_512_256, 0},
- {"blowfish192", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192},
- {"blowfish128", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128},
- {"sha256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
- {"aes192gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
+ {"modp2048s256", DIFFIE_HELLMAN_GROUP, MODP_2048_256, 0},
{"sha2_256", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_128, 0},
- {"aes128gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
- {"ecp384bp", DIFFIE_HELLMAN_GROUP, ECP_384_BP, 0},
+ {"sha384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0},
{"sha2_256_96", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_256_96, 0},
- {"blowfish256", ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 256},
- {"ecp224bp", DIFFIE_HELLMAN_GROUP, ECP_224_BP, 0},
+ {"camellia256ctr", ENCRYPTION_ALGORITHM, ENCR_CAMELLIA_CTR, 256},
+ {"twofish256", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 256},
+ {"aes192gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 192},
+ {"aes128gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 128},
{"sha1_160", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_160, 0},
+ {"twofish192", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 192},
+ {"ecp384bp", DIFFIE_HELLMAN_GROUP, ECP_384_BP, 0},
{"aes256gcm64", ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV8, 256},
- {"twofish", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
- {"prfcamelliaxcbc", PSEUDO_RANDOM_FUNCTION, PRF_CAMELLIA128_XCBC, 0},
- {"des", ENCRYPTION_ALGORITHM, ENCR_DES, 0},
+ {"chacha20poly1305", ENCRYPTION_ALGORITHM, ENCR_CHACHA20_POLY1305, 256},
+ {"ecp224bp", DIFFIE_HELLMAN_GROUP, ECP_224_BP, 0},
{"sha2_384", INTEGRITY_ALGORITHM, AUTH_HMAC_SHA2_384_192, 0},
- {"twofish128", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 128},
- {"modp2048s224", DIFFIE_HELLMAN_GROUP, MODP_2048_224, 0},
- {"twofish256", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 256},
- {"twofish192", ENCRYPTION_ALGORITHM, ENCR_TWOFISH_CBC, 192},
- {"prfaesxcbc", PSEUDO_RANDOM_FUNCTION, PRF_AES128_XCBC, 0},
- {"prfaescmac", PSEUDO_RANDOM_FUNCTION, PRF_AES128_CMAC, 0}
+ {"modp2048s224", DIFFIE_HELLMAN_GROUP, MODP_2048_224, 0}
};
static const short lookup[] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, 0, -1,
+ -1, -1, 1, 2, -1, 3, -1, 4, -1, -1,
+ 5, -1, -1, 6, -1, 7, -1, 8, -1, -1,
+ 9, -1, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, -1, 26,
+ -1, 27, 28, -1, -1, 29, 30, 31, -1, 32,
+ -1, 33, 34, 35, 36, -1, -1, 37, 38, -1,
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
+ 49, 50, 51, -1, 52, 53, 54, 55, 56, -1,
+ 57, 58, 59, -1, -1, -1, 60, 61, 62, 63,
+ -1, -1, 64, 65, -1, 66, -1, -1, 67, -1,
+ -1, -1, -1, 68, -1, 69, -1, 70, 71, -1,
+ 72, -1, -1, 73, 74, 75, 76, 77, 78, 79,
+ 80, -1, 81, 82, 83, 84, 85, 86, 87, 88,
+ 89, 90, 91, 92, -1, 93, 94, 95, 96, -1,
+ 97, 98, -1, 99, 100, 101, -1, 102, -1, -1,
+ 103, -1, -1, 104, 105, 106, 107, -1, 108, 109,
+ -1, 110, 111, -1, -1, 112, 113, -1, 114, -1,
+ -1, -1, -1, 115, -1, 116, 117, -1, 118, -1,
+ 119, 120, 121, 122, 123, -1, 124, 125, -1, 126,
+ -1, -1, 127, -1, 128, 129, -1, -1, 130, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 0, -1, 1, 2, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, 3, 4, -1, -1, -1, 5, -1,
- 6, 7, -1, -1, -1, -1, 8, -1, 9, 10,
- -1, -1, 11, -1, 12, -1, 13, -1, 14, 15,
- -1, 16, 17, 18, 19, 20, -1, -1, -1, 21,
- 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
- 32, 33, 34, 35, 36, 37, -1, 38, 39, -1,
- 40, 41, 42, -1, 43, 44, 45, 46, 47, 48,
- -1, 49, 50, 51, -1, 52, 53, 54, 55, 56,
- 57, 58, 59, -1, -1, 60, 61, 62, 63, 64,
- 65, 66, -1, -1, 67, 68, 69, 70, 71, 72,
- 73, 74, 75, 76, 77, 78, 79, 80, -1, 81,
- 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
- 92, 93, -1, 94, -1, 95, -1, 96, 97, 98,
- 99, 100, -1, 101, -1, 102, 103, 104, -1, 105,
- 106, 107, 108, 109, -1, 110, -1, 111, -1, 112,
- -1, 113, 114, 115, 116, -1, 117, 118, 119, 120,
- 121, -1, -1, -1, 122, -1, -1, 123, -1, -1,
- 124, -1, 125, 126, 127, -1, -1, -1, 128, -1,
- -1, -1, -1, -1, 129, 130, -1, 131, -1, 132,
- -1, -1, -1, -1, 133, -1, -1, -1, -1, 134,
- -1, -1, -1, -1, -1, 135, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 131, -1, 132, 133, -1, -1, 134, -1, -1, -1,
+ -1, 135, -1, -1, -1, -1, -1, -1, 136, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 136, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 137
+ -1, -1, 137, -1, -1, -1, 138
};
#ifdef __GNUC__
diff --git a/src/libstrongswan/crypto/proposal/proposal_keywords_static.txt b/src/libstrongswan/crypto/proposal/proposal_keywords_static.txt
index 70e79157a..da92409ca 100644
--- a/src/libstrongswan/crypto/proposal/proposal_keywords_static.txt
+++ b/src/libstrongswan/crypto/proposal/proposal_keywords_static.txt
@@ -78,6 +78,7 @@ aes256gcm128, ENCRYPTION_ALGORITHM, ENCR_AES_GCM_ICV16, 256
aes128gmac, ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 128
aes192gmac, ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 192
aes256gmac, ENCRYPTION_ALGORITHM, ENCR_NULL_AUTH_AES_GMAC, 256
+chacha20poly1305, ENCRYPTION_ALGORITHM, ENCR_CHACHA20_POLY1305, 256
blowfish, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128
blowfish128, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 128
blowfish192, ENCRYPTION_ALGORITHM, ENCR_BLOWFISH, 192
diff --git a/src/libstrongswan/networking/host.c b/src/libstrongswan/networking/host.c
index 07da3ef3b..2e464b0ad 100644
--- a/src/libstrongswan/networking/host.c
+++ b/src/libstrongswan/networking/host.c
@@ -354,6 +354,10 @@ host_t *host_create_from_string_and_family(char *string, int family,
struct sockaddr_in6 v6;
} addr;
+ if (!string)
+ {
+ return NULL;
+ }
if (streq(string, "%any"))
{
return host_create_any_port(family ? family : AF_INET, port);
diff --git a/src/libstrongswan/pen/pen.c b/src/libstrongswan/pen/pen.c
index 474a7a876..9fe47547e 100644
--- a/src/libstrongswan/pen/pen.c
+++ b/src/libstrongswan/pen/pen.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Andreas Steffen
+ * Copyright (C) 2011-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -23,7 +23,9 @@ ENUM_NEXT(pen_names, PEN_MICROSOFT, PEN_MICROSOFT, PEN_IBM,
"Microsoft");
ENUM_NEXT(pen_names, PEN_REDHAT, PEN_REDHAT, PEN_MICROSOFT,
"Redhat");
-ENUM_NEXT(pen_names, PEN_ALTIGA, PEN_ALTIGA, PEN_REDHAT,
+ENUM_NEXT(pen_names, PEN_PWG, PEN_PWG, PEN_REDHAT,
+ "PWG");
+ENUM_NEXT(pen_names, PEN_ALTIGA, PEN_ALTIGA, PEN_PWG,
"Altiga");
ENUM_NEXT(pen_names, PEN_OSC, PEN_OSC, PEN_ALTIGA,
"OSC");
diff --git a/src/libstrongswan/pen/pen.h b/src/libstrongswan/pen/pen.h
index 1760a0578..2c5592330 100644
--- a/src/libstrongswan/pen/pen.h
+++ b/src/libstrongswan/pen/pen.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2012 Andreas Steffen
+ * Copyright (C) 2011-2015 Andreas Steffen
* HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
@@ -39,6 +39,7 @@ enum pen_t {
PEN_IBM = 0x000002, /* 2 */
PEN_MICROSOFT = 0x000137, /* 311 */
PEN_REDHAT = 0x000908, /* 2312 */
+ PEN_PWG = 0x000A8B, /* 2699 */
PEN_ALTIGA = 0x000c04, /* 3076 */
PEN_OSC = 0x002358, /* 9048 */
PEN_DEBIAN = 0x002572, /* 9586 */
diff --git a/src/libstrongswan/plugins/bliss/bliss_private_key.c b/src/libstrongswan/plugins/bliss/bliss_private_key.c
index e1064d2f2..1386eeb2d 100644
--- a/src/libstrongswan/plugins/bliss/bliss_private_key.c
+++ b/src/libstrongswan/plugins/bliss/bliss_private_key.c
@@ -168,7 +168,7 @@ static bool sign_bliss(private_bliss_private_key_t *this, hash_algorithm_t alg,
bliss_sampler_t *sampler = NULL;
rng_t *rng;
hasher_t *hasher;
- hash_algorithm_t mgf1_alg;
+ hash_algorithm_t mgf1_alg, oracle_alg;
size_t mgf1_seed_len;
uint8_t mgf1_seed_buf[HASH_SIZE_SHA512], data_hash_buf[HASH_SIZE_SHA512];
chunk_t mgf1_seed, data_hash;
@@ -185,7 +185,7 @@ static bool sign_bliss(private_bliss_private_key_t *this, hash_algorithm_t alg,
/* Initialize signature */
*signature = chunk_empty;
- /* Create data hash */
+ /* Create data hash using configurable hash algorithm */
hasher = lib->crypto->create_hasher(lib->crypto, alg);
if (!hasher)
{
@@ -200,13 +200,6 @@ static bool sign_bliss(private_bliss_private_key_t *this, hash_algorithm_t alg,
}
hasher->destroy(hasher);
- /* Create SHA512 hasher for c_indices oracle */
- hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA512);
- if (!hasher)
- {
- return FALSE;
- }
-
/* Set MGF1 hash algorithm and seed length based on security strength */
if (this->set->strength > 160)
{
@@ -223,10 +216,12 @@ static bool sign_bliss(private_bliss_private_key_t *this, hash_algorithm_t alg,
rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG);
if (!rng)
{
- hasher->destroy(hasher);
return FALSE;
}
+ /* MGF1 hash algorithm to be used for random oracle */
+ oracle_alg = HASH_SHA512;
+
/* Initialize a couple of needed variables */
n = this->set->n;
q = this->set->q;
@@ -360,7 +355,7 @@ static bool sign_bliss(private_bliss_private_key_t *this, hash_algorithm_t alg,
DBG3(DBG_LIB, "%3d %6d %4d", i, u[i], ud[i]);
}
- if (!bliss_utils_generate_c(hasher, data_hash, ud, n, this->set->kappa,
+ if (!bliss_utils_generate_c(oracle_alg, data_hash, ud, this->set,
c_indices))
{
goto end;
@@ -495,7 +490,6 @@ static bool sign_bliss(private_bliss_private_key_t *this, hash_algorithm_t alg,
end:
/* cleanup */
DESTROY_IF(sampler);
- hasher->destroy(hasher);
sig->destroy(sig);
fft->destroy(fft);
rng->destroy(rng);
diff --git a/src/libstrongswan/plugins/bliss/bliss_public_key.c b/src/libstrongswan/plugins/bliss/bliss_public_key.c
index 0175b0f8e..2b305f6c2 100644
--- a/src/libstrongswan/plugins/bliss/bliss_public_key.c
+++ b/src/libstrongswan/plugins/bliss/bliss_public_key.c
@@ -70,11 +70,12 @@ static bool verify_bliss(private_bliss_public_key_t *this, hash_algorithm_t alg,
uint8_t data_hash_buf[HASH_SIZE_SHA512];
chunk_t data_hash;
hasher_t *hasher;
+ hash_algorithm_t oracle_alg;
bliss_fft_t *fft;
bliss_signature_t *sig;
bool success = FALSE;
- /* Create data hash */
+ /* Create data hash using configurable hash algorithm */
hasher = lib->crypto->create_hasher(lib->crypto, alg);
if (!hasher )
{
@@ -89,28 +90,22 @@ static bool verify_bliss(private_bliss_public_key_t *this, hash_algorithm_t alg,
}
hasher->destroy(hasher);
- /* Create SHA512 hasher for c_indices oracle */
- hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA512);
- if (!hasher)
- {
- return FALSE;
- }
-
sig = bliss_signature_create_from_data(this->set, signature);
if (!sig)
{
- hasher->destroy(hasher);
return FALSE;
}
sig->get_parameters(sig, &z1, &z2d, &c_indices);
if (!bliss_utils_check_norms(this->set, z1, z2d))
{
- hasher->destroy(hasher);
sig->destroy(sig);
return FALSE;
}
+ /* MGF1 hash algorithm to be used for random oracle */
+ oracle_alg = HASH_SHA512;
+
/* Initialize a couple of needed variables */
n = this->set->n;
q = this->set->q;
@@ -165,8 +160,7 @@ static bool verify_bliss(private_bliss_public_key_t *this, hash_algorithm_t alg,
DBG3(DBG_LIB, "%3d %6d %4d %4d", i, u[i], ud[i], z2d[i]);
}
- if (!bliss_utils_generate_c(hasher, data_hash, ud, n, this->set->kappa,
- indices))
+ if (!bliss_utils_generate_c(oracle_alg, data_hash, ud, this->set, indices))
{
goto end;
}
@@ -183,7 +177,6 @@ static bool verify_bliss(private_bliss_public_key_t *this, hash_algorithm_t alg,
end:
/* cleanup */
- hasher->destroy(hasher);
sig->destroy(sig);
fft->destroy(fft);
free(az);
diff --git a/src/libstrongswan/plugins/bliss/bliss_utils.c b/src/libstrongswan/plugins/bliss/bliss_utils.c
index 5a069989c..5e313ff26 100644
--- a/src/libstrongswan/plugins/bliss/bliss_utils.c
+++ b/src/libstrongswan/plugins/bliss/bliss_utils.c
@@ -17,6 +17,7 @@
#include <asn1/asn1.h>
#include <crypto/hashers/hasher.h>
+#include <crypto/mgf1/mgf1_bitspender.h>
#include <utils/debug.h>
/**
@@ -54,55 +55,63 @@ void bliss_utils_round_and_drop(bliss_param_set_t *set, int32_t *x, int16_t *xd)
/**
* See header.
*/
-bool bliss_utils_generate_c(hasher_t *hasher, chunk_t data_hash, uint16_t *ud,
- int n, uint16_t kappa, uint16_t *c_indices)
+bool bliss_utils_generate_c(hash_algorithm_t alg, chunk_t data_hash,
+ uint16_t *ud, bliss_param_set_t *set,
+ uint16_t *c_indices)
{
- int i, j;
- uint64_t extra_bits;
- uint16_t index, rounds = 0;
- uint8_t hash[HASH_SIZE_SHA512], un16_buf[2];
- chunk_t un16 = { un16_buf, 2 };
- bool index_taken[n];
-
- while (TRUE)
+ int i, index_trials = 0, index_found = 0;
+ bool index_taken[set->n];
+ uint32_t index;
+ uint8_t *seed_pos;
+ chunk_t seed;
+ mgf1_bitspender_t *bitspender;
+
+ seed = chunk_alloca(data_hash.len + set->n * sizeof(uint16_t));
+
+ /* the data hash makes up the first part of the oracle seed */
+ memcpy(seed.ptr, data_hash.ptr, data_hash.len);
+ seed_pos = seed.ptr + data_hash.len;
+
+ /* followed by the n elements of the ud vector in network order */
+ for (i = 0; i < set->n; i++)
{
- if (!hasher->get_hash(hasher, data_hash, NULL))
- {
- return FALSE;
- }
+ htoun16(seed_pos, ud[i]);
+ seed_pos += sizeof(uint16_t);
+ }
- for (i = 0; i < n; i++)
- {
- htoun16(un16_buf, ud[i]);
- if (!hasher->get_hash(hasher, un16, NULL))
- {
- return FALSE;
- }
- index_taken[i] = FALSE;
- }
+ bitspender = mgf1_bitspender_create(alg, seed, FALSE);
+ if (!bitspender)
+ {
+ return NULL;
+ }
- htoun16(un16_buf, rounds++);
- if (!hasher->get_hash(hasher, un16, hash))
- {
- return FALSE;
- }
+ for (i = 0; i < set->n; i++)
+ {
+ index_taken[i] = FALSE;
+ }
- extra_bits = untoh64(hash + sizeof(hash) - sizeof(uint64_t));
+ DBG3(DBG_LIB, " i c_index[i]");
+ while (bitspender->get_bits(bitspender, set->n_bits, &index))
+ {
+ index_trials++;
- for (i = 0, j = 0; j < sizeof(hash); j++)
+ if (!index_taken[index])
{
- index = 2 * (uint16_t)hash[i] + (extra_bits & 1);
- if (!index_taken[index])
- {
- c_indices[i++] = index;
- index_taken[index] = TRUE;
- }
- if (i == kappa)
+ DBG3(DBG_LIB, "%2u %8u", index_found, index);
+ c_indices[index_found++] = index;
+ index_taken[index] = TRUE;
+
+ if (index_found == set->kappa)
{
+ DBG3(DBG_LIB, "%2d index trials", index_trials);
+ bitspender->destroy(bitspender);
return TRUE;
}
}
}
+
+ bitspender->destroy(bitspender);
+ return FALSE;
}
/**
diff --git a/src/libstrongswan/plugins/bliss/bliss_utils.h b/src/libstrongswan/plugins/bliss/bliss_utils.h
index 063fd91c8..156968dd7 100644
--- a/src/libstrongswan/plugins/bliss/bliss_utils.h
+++ b/src/libstrongswan/plugins/bliss/bliss_utils.h
@@ -47,15 +47,15 @@ void bliss_utils_round_and_drop(bliss_param_set_t *set, int32_t *x, int16_t *xd)
/**
* Generate the binary challenge vector c as an array of kappa indices
*
- * @param hasher hasher used as an oracle
+ * @param alg hash algorithm to be used for the internal oracle
* @param data_hash hash of the data to be signed
* @param ud input vector ud of size n
- * @param n size of input vector ud
- * @param kappa parameter kappa
+ * @param set BLISS parameter set to be used (n, n_bits, kappa)
* @param c_indices indexes of non-zero challenge coefficients
*/
-bool bliss_utils_generate_c(hasher_t *hasher, chunk_t data_hash, uint16_t *ud,
- int n, uint16_t kappa, uint16_t *c_indices);
+bool bliss_utils_generate_c(hash_algorithm_t alg, chunk_t data_hash,
+ uint16_t *ud, bliss_param_set_t *set,
+ uint16_t *c_indices);
/**
* Check the infinity and l2 norms of the vectors z1 and z2d << d
diff --git a/src/libstrongswan/plugins/chapoly/Makefile.am b/src/libstrongswan/plugins/chapoly/Makefile.am
new file mode 100644
index 000000000..1753de0c7
--- /dev/null
+++ b/src/libstrongswan/plugins/chapoly/Makefile.am
@@ -0,0 +1,29 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+noinst_LTLIBRARIES =
+if MONOLITHIC
+noinst_LTLIBRARIES += libstrongswan-chapoly.la
+else
+plugin_LTLIBRARIES = libstrongswan-chapoly.la
+endif
+
+libstrongswan_chapoly_la_SOURCES = \
+ chapoly_plugin.h chapoly_plugin.c \
+ chapoly_drv.h chapoly_drv.c \
+ chapoly_drv_portable.h chapoly_drv_portable.c \
+ chapoly_aead.h chapoly_aead.c
+
+noinst_LTLIBRARIES += libchapoly-drv-ssse3.la
+libchapoly_drv_ssse3_la_SOURCES = chapoly_drv_ssse3.h chapoly_drv_ssse3.c
+if USE_X86X64
+ libchapoly_drv_ssse3_la_CFLAGS = $(PLUGIN_CFLAGS) -mssse3
+endif
+
+libstrongswan_chapoly_la_LIBADD = \
+ libchapoly-drv-ssse3.la
+
+libstrongswan_chapoly_la_LDFLAGS = -module -avoid-version
diff --git a/src/libstrongswan/plugins/chapoly/Makefile.in b/src/libstrongswan/plugins/chapoly/Makefile.in
new file mode 100644
index 000000000..98e1f4d9e
--- /dev/null
+++ b/src/libstrongswan/plugins/chapoly/Makefile.in
@@ -0,0 +1,810 @@
+# 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@
+@MONOLITHIC_TRUE@am__append_1 = libstrongswan-chapoly.la
+subdir = src/libstrongswan/plugins/chapoly
+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)
+libchapoly_drv_ssse3_la_LIBADD =
+am_libchapoly_drv_ssse3_la_OBJECTS = \
+ libchapoly_drv_ssse3_la-chapoly_drv_ssse3.lo
+libchapoly_drv_ssse3_la_OBJECTS = \
+ $(am_libchapoly_drv_ssse3_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 =
+libchapoly_drv_ssse3_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libchapoly_drv_ssse3_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
+libstrongswan_chapoly_la_DEPENDENCIES = libchapoly-drv-ssse3.la
+am_libstrongswan_chapoly_la_OBJECTS = chapoly_plugin.lo chapoly_drv.lo \
+ chapoly_drv_portable.lo chapoly_aead.lo
+libstrongswan_chapoly_la_OBJECTS = \
+ $(am_libstrongswan_chapoly_la_OBJECTS)
+libstrongswan_chapoly_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(AM_CFLAGS) $(CFLAGS) $(libstrongswan_chapoly_la_LDFLAGS) \
+ $(LDFLAGS) -o $@
+@MONOLITHIC_FALSE@am_libstrongswan_chapoly_la_rpath = -rpath \
+@MONOLITHIC_FALSE@ $(plugindir)
+@MONOLITHIC_TRUE@am_libstrongswan_chapoly_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 = $(libchapoly_drv_ssse3_la_SOURCES) \
+ $(libstrongswan_chapoly_la_SOURCES)
+DIST_SOURCES = $(libchapoly_drv_ssse3_la_SOURCES) \
+ $(libstrongswan_chapoly_la_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
+# Read a list of newline-separated strings from the standard input,
+# and print each of them once, without duplicates. Input order is
+# *not* preserved.
+am__uniquify_input = $(AWK) '\
+ BEGIN { nonempty = 0; } \
+ { items[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in items) print i; }; } \
+'
+# Make sure the list of sources is unique. This is necessary because,
+# e.g., the same source file might be shared among _SOURCES variables
+# for different programs/libraries.
+am__define_uniq_tagged_files = \
+ list='$(am__tagged_files)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | $(am__uniquify_input)`
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALLOCA = @ALLOCA@
+AMTAR = @AMTAR@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BFDLIB = @BFDLIB@
+BTLIB = @BTLIB@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLIB = @DLLIB@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+EASY_INSTALL = @EASY_INSTALL@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GEM = @GEM@
+GENHTML = @GENHTML@
+GPERF = @GPERF@
+GPRBUILD = @GPRBUILD@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LEX = @LEX@
+LEXLIB = @LEXLIB@
+LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MYSQLCFLAG = @MYSQLCFLAG@
+MYSQLCONFIG = @MYSQLCONFIG@
+MYSQLLIB = @MYSQLLIB@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OPENSSL_LIB = @OPENSSL_LIB@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PACKAGE_VERSION_BUILD = @PACKAGE_VERSION_BUILD@
+PACKAGE_VERSION_MAJOR = @PACKAGE_VERSION_MAJOR@
+PACKAGE_VERSION_MINOR = @PACKAGE_VERSION_MINOR@
+PACKAGE_VERSION_REVIEW = @PACKAGE_VERSION_REVIEW@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PERL = @PERL@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+PLUGIN_CFLAGS = @PLUGIN_CFLAGS@
+PTHREADLIB = @PTHREADLIB@
+PYTHON = @PYTHON@
+PYTHONEGGINSTALLDIR = @PYTHONEGGINSTALLDIR@
+PYTHON_EXEC_PREFIX = @PYTHON_EXEC_PREFIX@
+PYTHON_PLATFORM = @PYTHON_PLATFORM@
+PYTHON_PREFIX = @PYTHON_PREFIX@
+PYTHON_VERSION = @PYTHON_VERSION@
+PY_TEST = @PY_TEST@
+RANLIB = @RANLIB@
+RTLIB = @RTLIB@
+RUBY = @RUBY@
+RUBYGEMDIR = @RUBYGEMDIR@
+RUBYINCLUDE = @RUBYINCLUDE@
+RUBYLIB = @RUBYLIB@
+SED = @SED@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SOCKLIB = @SOCKLIB@
+STRIP = @STRIP@
+UNWINDLIB = @UNWINDLIB@
+VERSION = @VERSION@
+YACC = @YACC@
+YFLAGS = @YFLAGS@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+aikgen_plugins = @aikgen_plugins@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+attest_plugins = @attest_plugins@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+c_plugins = @c_plugins@
+charon_natt_port = @charon_natt_port@
+charon_plugins = @charon_plugins@
+charon_udp_port = @charon_udp_port@
+clearsilver_LIBS = @clearsilver_LIBS@
+cmd_plugins = @cmd_plugins@
+datadir = @datadir@
+datarootdir = @datarootdir@
+dbusservicedir = @dbusservicedir@
+dev_headers = @dev_headers@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+fips_mode = @fips_mode@
+gtk_CFLAGS = @gtk_CFLAGS@
+gtk_LIBS = @gtk_LIBS@
+h_plugins = @h_plugins@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+imcvdir = @imcvdir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+ipsec_script = @ipsec_script@
+ipsec_script_upper = @ipsec_script_upper@
+ipsecdir = @ipsecdir@
+ipsecgroup = @ipsecgroup@
+ipseclibdir = @ipseclibdir@
+ipsecuser = @ipsecuser@
+json_CFLAGS = @json_CFLAGS@
+json_LIBS = @json_LIBS@
+libdir = @libdir@
+libexecdir = @libexecdir@
+libiptc_CFLAGS = @libiptc_CFLAGS@
+libiptc_LIBS = @libiptc_LIBS@
+linux_headers = @linux_headers@
+localedir = @localedir@
+localstatedir = @localstatedir@
+maemo_CFLAGS = @maemo_CFLAGS@
+maemo_LIBS = @maemo_LIBS@
+manager_plugins = @manager_plugins@
+mandir = @mandir@
+medsrv_plugins = @medsrv_plugins@
+mkdir_p = @mkdir_p@
+nm_CFLAGS = @nm_CFLAGS@
+nm_LIBS = @nm_LIBS@
+nm_ca_dir = @nm_ca_dir@
+nm_plugins = @nm_plugins@
+oldincludedir = @oldincludedir@
+pcsclite_CFLAGS = @pcsclite_CFLAGS@
+pcsclite_LIBS = @pcsclite_LIBS@
+pdfdir = @pdfdir@
+piddir = @piddir@
+pkgpyexecdir = @pkgpyexecdir@
+pkgpythondir = @pkgpythondir@
+pki_plugins = @pki_plugins@
+plugindir = @plugindir@
+pool_plugins = @pool_plugins@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+pyexecdir = @pyexecdir@
+pythondir = @pythondir@
+random_device = @random_device@
+resolv_conf = @resolv_conf@
+routing_table = @routing_table@
+routing_table_prio = @routing_table_prio@
+s_plugins = @s_plugins@
+sbindir = @sbindir@
+scepclient_plugins = @scepclient_plugins@
+scripts_plugins = @scripts_plugins@
+sharedstatedir = @sharedstatedir@
+soup_CFLAGS = @soup_CFLAGS@
+soup_LIBS = @soup_LIBS@
+srcdir = @srcdir@
+starter_plugins = @starter_plugins@
+strongswan_conf = @strongswan_conf@
+strongswan_options = @strongswan_options@
+swanctldir = @swanctldir@
+sysconfdir = @sysconfdir@
+systemd_daemon_CFLAGS = @systemd_daemon_CFLAGS@
+systemd_daemon_LIBS = @systemd_daemon_LIBS@
+systemd_journal_CFLAGS = @systemd_journal_CFLAGS@
+systemd_journal_LIBS = @systemd_journal_LIBS@
+systemdsystemunitdir = @systemdsystemunitdir@
+t_plugins = @t_plugins@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+urandom_device = @urandom_device@
+xml_CFLAGS = @xml_CFLAGS@
+xml_LIBS = @xml_LIBS@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan
+
+AM_CFLAGS = \
+ $(PLUGIN_CFLAGS)
+
+noinst_LTLIBRARIES = $(am__append_1) libchapoly-drv-ssse3.la
+@MONOLITHIC_FALSE@plugin_LTLIBRARIES = libstrongswan-chapoly.la
+libstrongswan_chapoly_la_SOURCES = \
+ chapoly_plugin.h chapoly_plugin.c \
+ chapoly_drv.h chapoly_drv.c \
+ chapoly_drv_portable.h chapoly_drv_portable.c \
+ chapoly_aead.h chapoly_aead.c
+
+libchapoly_drv_ssse3_la_SOURCES = chapoly_drv_ssse3.h chapoly_drv_ssse3.c
+@USE_X86X64_TRUE@libchapoly_drv_ssse3_la_CFLAGS = $(PLUGIN_CFLAGS) -mssse3
+libstrongswan_chapoly_la_LIBADD = \
+ libchapoly-drv-ssse3.la
+
+libstrongswan_chapoly_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/libstrongswan/plugins/chapoly/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/libstrongswan/plugins/chapoly/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}; \
+ }
+
+libchapoly-drv-ssse3.la: $(libchapoly_drv_ssse3_la_OBJECTS) $(libchapoly_drv_ssse3_la_DEPENDENCIES) $(EXTRA_libchapoly_drv_ssse3_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libchapoly_drv_ssse3_la_LINK) $(libchapoly_drv_ssse3_la_OBJECTS) $(libchapoly_drv_ssse3_la_LIBADD) $(LIBS)
+
+libstrongswan-chapoly.la: $(libstrongswan_chapoly_la_OBJECTS) $(libstrongswan_chapoly_la_DEPENDENCIES) $(EXTRA_libstrongswan_chapoly_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libstrongswan_chapoly_la_LINK) $(am_libstrongswan_chapoly_la_rpath) $(libstrongswan_chapoly_la_OBJECTS) $(libstrongswan_chapoly_la_LIBADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chapoly_aead.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chapoly_drv.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chapoly_drv_portable.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/chapoly_plugin.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libchapoly_drv_ssse3_la-chapoly_drv_ssse3.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 $@ $<
+
+libchapoly_drv_ssse3_la-chapoly_drv_ssse3.lo: chapoly_drv_ssse3.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libchapoly_drv_ssse3_la_CFLAGS) $(CFLAGS) -MT libchapoly_drv_ssse3_la-chapoly_drv_ssse3.lo -MD -MP -MF $(DEPDIR)/libchapoly_drv_ssse3_la-chapoly_drv_ssse3.Tpo -c -o libchapoly_drv_ssse3_la-chapoly_drv_ssse3.lo `test -f 'chapoly_drv_ssse3.c' || echo '$(srcdir)/'`chapoly_drv_ssse3.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libchapoly_drv_ssse3_la-chapoly_drv_ssse3.Tpo $(DEPDIR)/libchapoly_drv_ssse3_la-chapoly_drv_ssse3.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='chapoly_drv_ssse3.c' object='libchapoly_drv_ssse3_la-chapoly_drv_ssse3.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libchapoly_drv_ssse3_la_CFLAGS) $(CFLAGS) -c -o libchapoly_drv_ssse3_la-chapoly_drv_ssse3.lo `test -f 'chapoly_drv_ssse3.c' || echo '$(srcdir)/'`chapoly_drv_ssse3.c
+
+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/libstrongswan/plugins/chapoly/chapoly_aead.c b/src/libstrongswan/plugins/chapoly/chapoly_aead.c
new file mode 100644
index 000000000..50ad84b21
--- /dev/null
+++ b/src/libstrongswan/plugins/chapoly/chapoly_aead.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "chapoly_aead.h"
+#include "chapoly_drv.h"
+
+#include <crypto/iv/iv_gen_seq.h>
+
+/* maximum plain message size */
+#define P_MAX 247877906880
+
+typedef struct private_chapoly_aead_t private_chapoly_aead_t;
+
+/**
+ * Private data of an chapoly_aead_t object.
+ */
+struct private_chapoly_aead_t {
+
+ /**
+ * Public chapoly_aead_t interface.
+ */
+ chapoly_aead_t public;
+
+ /**
+ * IV generator.
+ */
+ iv_gen_t *iv_gen;
+
+ /**
+ * Driver backend
+ */
+ chapoly_drv_t *drv;
+};
+
+/**
+ * Include a partial block to ICV by padding it with zero bytes
+ */
+static bool poly_update_padded(private_chapoly_aead_t *this,
+ u_char *in, size_t len)
+{
+ u_char b[POLY_BLOCK_SIZE];
+
+ memset(b, 0, sizeof(b));
+ memcpy(b, in, len);
+
+ return this->drv->poly(this->drv, b, 1);
+}
+
+/**
+ * Include associated data with padding to ICV
+ */
+static bool poly_head(private_chapoly_aead_t *this, u_char *assoc, size_t len)
+{
+ u_int blocks, rem;
+
+ blocks = len / POLY_BLOCK_SIZE;
+ rem = len % POLY_BLOCK_SIZE;
+ if (!this->drv->poly(this->drv, assoc, blocks))
+ {
+ return FALSE;
+ }
+ if (rem)
+ {
+ return poly_update_padded(this, assoc + blocks * POLY_BLOCK_SIZE, rem);
+ }
+ return TRUE;
+}
+
+/**
+ * Include length fields to ICV
+ */
+static bool poly_tail(private_chapoly_aead_t *this, size_t alen, size_t clen)
+{
+ struct {
+ u_int64_t alen;
+ u_int64_t clen;
+ } b;
+
+ b.alen = htole64(alen);
+ b.clen = htole64(clen);
+
+ return this->drv->poly(this->drv, (u_char*)&b, 1);
+}
+
+/**
+ * Perform ChaCha20 encryption inline and generate an ICV tag
+ */
+static bool do_encrypt(private_chapoly_aead_t *this, size_t len, u_char *data,
+ u_char *iv, size_t alen, u_char *assoc, u_char *icv)
+{
+ u_int blocks, rem, prem;
+
+ if (!this->drv->init(this->drv, iv) ||
+ !poly_head(this, assoc, alen))
+ {
+ return FALSE;
+ }
+ blocks = len / CHACHA_BLOCK_SIZE;
+ if (!this->drv->encrypt(this->drv, data, blocks))
+ {
+ return FALSE;
+ }
+ rem = len % CHACHA_BLOCK_SIZE;
+ if (rem)
+ {
+ u_char stream[CHACHA_BLOCK_SIZE];
+
+ data += blocks * CHACHA_BLOCK_SIZE;
+ if (!this->drv->chacha(this->drv, stream))
+ {
+ return FALSE;
+ }
+ memxor(data, stream, rem);
+
+ blocks = rem / POLY_BLOCK_SIZE;
+ if (!this->drv->poly(this->drv, data, blocks))
+ {
+ return FALSE;
+ }
+ prem = rem % POLY_BLOCK_SIZE;
+ if (prem)
+ {
+ poly_update_padded(this, data + blocks * POLY_BLOCK_SIZE, prem);
+ }
+ }
+ return poly_tail(this, alen, len) &&
+ this->drv->finish(this->drv, icv);
+}
+
+/**
+ * Perform ChaCha20 decryption inline and generate an ICV tag
+ */
+static bool do_decrypt(private_chapoly_aead_t *this, size_t len, u_char *data,
+ u_char *iv, size_t alen, u_char *assoc, u_char *icv)
+{
+ u_int blocks, rem, prem;
+
+ if (!this->drv->init(this->drv, iv) ||
+ !poly_head(this, assoc, alen))
+ {
+ return FALSE;
+ }
+ blocks = len / CHACHA_BLOCK_SIZE;
+ if (!this->drv->decrypt(this->drv, data, blocks))
+ {
+ return FALSE;
+ }
+ rem = len % CHACHA_BLOCK_SIZE;
+ if (rem)
+ {
+ u_char stream[CHACHA_BLOCK_SIZE];
+
+ data += blocks * CHACHA_BLOCK_SIZE;
+
+ blocks = rem / POLY_BLOCK_SIZE;
+ if (!this->drv->poly(this->drv, data, blocks))
+ {
+ return FALSE;
+ }
+ prem = rem % POLY_BLOCK_SIZE;
+ if (prem)
+ {
+ poly_update_padded(this, data + blocks * POLY_BLOCK_SIZE, prem);
+ }
+ if (!this->drv->chacha(this->drv, stream))
+ {
+ return FALSE;
+ }
+ memxor(data, stream, rem);
+ }
+ return poly_tail(this, alen, len) &&
+ this->drv->finish(this->drv, icv);
+}
+
+METHOD(aead_t, encrypt, bool,
+ private_chapoly_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
+ chunk_t *encr)
+{
+ u_char *out;
+
+ if (sizeof(plain.len) > sizeof(u_int32_t) && plain.len > P_MAX)
+ {
+ return FALSE;
+ }
+ if (iv.len != CHACHA_IV_SIZE)
+ {
+ return FALSE;
+ }
+ out = plain.ptr;
+ if (encr)
+ {
+ *encr = chunk_alloc(plain.len + POLY_ICV_SIZE);
+ out = encr->ptr;
+ memcpy(out, plain.ptr, plain.len);
+ }
+ do_encrypt(this, plain.len, out, iv.ptr, assoc.len, assoc.ptr,
+ out + plain.len);
+ return TRUE;
+}
+
+METHOD(aead_t, decrypt, bool,
+ private_chapoly_aead_t *this, chunk_t encr, chunk_t assoc, chunk_t iv,
+ chunk_t *plain)
+{
+ u_char *out, icv[POLY_ICV_SIZE];
+ if (iv.len != CHACHA_IV_SIZE || encr.len < POLY_ICV_SIZE)
+ {
+ return FALSE;
+ }
+ encr.len -= POLY_ICV_SIZE;
+ if (sizeof(encr.len) > sizeof(u_int32_t) && encr.len > P_MAX)
+ {
+ return FALSE;
+ }
+ out = encr.ptr;
+ if (plain)
+ {
+ *plain = chunk_alloc(encr.len);
+ out = plain->ptr;
+ memcpy(out, encr.ptr, encr.len);
+ }
+ do_decrypt(this, encr.len, out, iv.ptr, assoc.len, assoc.ptr, icv);
+ return memeq_const(icv, encr.ptr + encr.len, POLY_ICV_SIZE);
+}
+
+METHOD(aead_t, get_block_size, size_t,
+ private_chapoly_aead_t *this)
+{
+ return 1;
+}
+
+METHOD(aead_t, get_icv_size, size_t,
+ private_chapoly_aead_t *this)
+{
+ return POLY_ICV_SIZE;
+}
+
+METHOD(aead_t, get_iv_size, size_t,
+ private_chapoly_aead_t *this)
+{
+ return CHACHA_IV_SIZE;
+}
+
+METHOD(aead_t, get_iv_gen, iv_gen_t*,
+ private_chapoly_aead_t *this)
+{
+ return this->iv_gen;
+}
+
+METHOD(aead_t, get_key_size, size_t,
+ private_chapoly_aead_t *this)
+{
+ return CHACHA_KEY_SIZE + CHACHA_SALT_SIZE;
+}
+
+METHOD(aead_t, set_key, bool,
+ private_chapoly_aead_t *this, chunk_t key)
+{
+ if (key.len != CHACHA_KEY_SIZE + CHACHA_SALT_SIZE)
+ {
+ return FALSE;
+ }
+ return this->drv->set_key(this->drv, "expand 32-byte k",
+ key.ptr, key.ptr + CHACHA_KEY_SIZE);
+}
+
+METHOD(aead_t, destroy, void,
+ private_chapoly_aead_t *this)
+{
+ this->drv->destroy(this->drv);
+ this->iv_gen->destroy(this->iv_gen);
+ free(this);
+}
+
+/**
+ * See header
+ */
+chapoly_aead_t *chapoly_aead_create(encryption_algorithm_t algo,
+ size_t key_size, size_t salt_size)
+{
+ private_chapoly_aead_t *this;
+ chapoly_drv_t *drv;
+
+ if (algo != ENCR_CHACHA20_POLY1305)
+ {
+ return NULL;
+ }
+ if (key_size && key_size != CHACHA_KEY_SIZE)
+ {
+ return NULL;
+ }
+ if (salt_size && salt_size != CHACHA_SALT_SIZE)
+ {
+ return NULL;
+ }
+ drv = chapoly_drv_probe();
+ if (!drv)
+ {
+ return NULL;
+ }
+
+ INIT(this,
+ .public = {
+ .aead = {
+ .encrypt = _encrypt,
+ .decrypt = _decrypt,
+ .get_block_size = _get_block_size,
+ .get_icv_size = _get_icv_size,
+ .get_iv_size = _get_iv_size,
+ .get_iv_gen = _get_iv_gen,
+ .get_key_size = _get_key_size,
+ .set_key = _set_key,
+ .destroy = _destroy,
+ },
+ },
+ .iv_gen = iv_gen_seq_create(),
+ .drv = drv,
+ );
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/plugins/chapoly/chapoly_aead.h b/src/libstrongswan/plugins/chapoly/chapoly_aead.h
new file mode 100644
index 000000000..e090541dd
--- /dev/null
+++ b/src/libstrongswan/plugins/chapoly/chapoly_aead.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup chapoly_aead chapoly_aead
+ * @{ @ingroup chapoly
+ */
+
+#ifndef CHAPOLY_AEAD_H_
+#define CHAPOLY_AEAD_H_
+
+#include <crypto/aead.h>
+
+typedef struct chapoly_aead_t chapoly_aead_t;
+
+/**
+ * ChaCha20/Poly1305 AEAD implementation.
+ *
+ * TODO-Chapoly: draft-ietf-ipsecme-chacha20-poly1305-05
+ */
+struct chapoly_aead_t {
+
+ /**
+ * Implements aead_t interface.
+ */
+ aead_t aead;
+};
+
+/**
+ * Create a chapoly_aead instance.
+ *
+ * @param algo algorithm to implement, ENCR_CHACHA20_POLY1305
+ * @param key_size key size in bytes, 32
+ * @param salt_size size of implicit salt length, 0
+ * @return AEAD, NULL if not supported
+ */
+chapoly_aead_t *chapoly_aead_create(encryption_algorithm_t algo,
+ size_t key_size, size_t salt_size);
+
+#endif /** CHAPOLY_AEAD_H_ @}*/
diff --git a/src/libstrongswan/plugins/chapoly/chapoly_drv.c b/src/libstrongswan/plugins/chapoly/chapoly_drv.c
new file mode 100644
index 000000000..ca5e2be08
--- /dev/null
+++ b/src/libstrongswan/plugins/chapoly/chapoly_drv.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "chapoly_drv.h"
+#include "chapoly_drv_portable.h"
+#include "chapoly_drv_ssse3.h"
+
+typedef chapoly_drv_t*(*chapoly_drv_create)();
+
+/**
+ * See header.
+ */
+chapoly_drv_t *chapoly_drv_probe()
+{
+ chapoly_drv_create drivers[] = {
+ chapoly_drv_ssse3_create,
+ chapoly_drv_portable_create,
+ };
+ chapoly_drv_t *driver;
+ int i;
+
+ for (i = 0; i < countof(drivers); i++)
+ {
+ driver = drivers[i]();
+ if (driver)
+ {
+ return driver;
+ }
+ }
+ return NULL;
+}
diff --git a/src/libstrongswan/plugins/chapoly/chapoly_drv.h b/src/libstrongswan/plugins/chapoly/chapoly_drv.h
new file mode 100644
index 000000000..bffc43447
--- /dev/null
+++ b/src/libstrongswan/plugins/chapoly/chapoly_drv.h
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup chapoly_drv chapoly_drv
+ * @{ @ingroup chapoly
+ */
+
+#ifndef CHAPOLY_DRV_H_
+#define CHAPOLY_DRV_H_
+
+#include <library.h>
+
+#define CHACHA_BLOCK_SIZE 64
+#define CHACHA_IV_SIZE 8
+#define CHACHA_SALT_SIZE 4
+#define CHACHA_KEY_SIZE 32
+#define POLY_BLOCK_SIZE 16
+#define POLY_ICV_SIZE 16
+
+typedef struct chapoly_drv_t chapoly_drv_t;
+
+/**
+ * ChaCha20/Poly1305 backend implementation.
+ */
+struct chapoly_drv_t {
+
+ /**
+ * Set the ChaCha20 encryption key.
+ *
+ * @param constant 16 byte key constant to use
+ * @param key 32 byte encryption key
+ * @param salt 4 byte nonce salt
+ * @return TRUE if key set
+ */
+ bool (*set_key)(chapoly_drv_t *this, u_char *constant, u_char *key,
+ u_char *salt);
+
+ /**
+ * Start an AEAD en/decryption session, reset state.
+ *
+ * @param iv 8 byte initialization vector for nonce
+ * @return TRUE if initialized
+ */
+ bool (*init)(chapoly_drv_t *this, u_char *iv);
+
+ /**
+ * Poly1305 update multiple blocks.
+ *
+ * @param data data to update Poly1305 for
+ * @param blocks number of 16-byte blocks to process
+ * @return TRUE if updated
+ */
+ bool (*poly)(chapoly_drv_t *this, u_char *data, u_int blocks);
+
+ /**
+ * Create a single ChaCha20 keystream block.
+ *
+ * @param stream 64-byte block to write key stream data to
+ * @return TRUE if keystream returned
+ */
+ bool (*chacha)(chapoly_drv_t *this, u_char *stream);
+
+ /**
+ * Encrypt multiple blocks of data inline, update Poly1305.
+ *
+ * @param data data to process
+ * @param blocks number of 64-byte blocks to process
+ * @return TRUE if encrypted
+ */
+ bool (*encrypt)(chapoly_drv_t *this, u_char *data, u_int blocks);
+
+ /**
+ * Decrypt multiple blocks of data inline, update Poly1305.
+ *
+ * @param data data to process
+ * @param blocks number of 64-byte blocks to process
+ * @return TRUE if decrypted
+ */
+ bool (*decrypt)(chapoly_drv_t *this, u_char *data, u_int blocks);
+
+ /**
+ * End a AEAD encryption session, return MAC.
+ *
+ * @param mac 16-byte block to write MAC to
+ * @return TRUE if MAC returned
+ */
+ bool (*finish)(chapoly_drv_t *this, u_char *mac);
+
+ /**
+ * Destroy a chapoly_drv_t.
+ */
+ void (*destroy)(chapoly_drv_t *this);
+};
+
+/**
+ * Create a chapoly_drv instance.
+ */
+chapoly_drv_t *chapoly_drv_probe();
+
+#endif /** CHAPOLY_DRV_H_ @}*/
diff --git a/src/libstrongswan/plugins/chapoly/chapoly_drv_portable.c b/src/libstrongswan/plugins/chapoly/chapoly_drv_portable.c
new file mode 100644
index 000000000..54e934e6a
--- /dev/null
+++ b/src/libstrongswan/plugins/chapoly/chapoly_drv_portable.c
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * Based on public domain code by Andrew Moon and Daniel J. Bernstein.
+ *
+ * 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 "chapoly_drv_portable.h"
+
+#define CHACHA_DOUBLEROUNDS 10
+/* index of some state fields */
+#define CHACHA_BLOCKCOUNT 12
+#define CHACHA_NONCE1 13
+#define CHACHA_NONCE2 14
+#define CHACHA_NONCE3 15
+
+typedef struct private_chapoly_drv_portable_t private_chapoly_drv_portable_t;
+
+/**
+ * Private data of an chapoly_drv_portable_t object.
+ */
+struct private_chapoly_drv_portable_t {
+
+ /**
+ * Public chapoly_drv_portable_t interface.
+ */
+ chapoly_drv_t public;
+
+ /**
+ * ChaCha20 state matrix
+ */
+ u_int32_t m[16];
+
+ /**
+ * Poly1305 update key
+ */
+ u_int32_t r[5];
+
+ /**
+ * Poly1305 state
+ */
+ u_int32_t h[5];
+
+ /**
+ * Poly1305 finalize key
+ */
+ u_int32_t s[4];
+};
+
+/**
+ * Convert unaligned little endian to host byte order
+ */
+static inline u_int32_t uletoh32(void *p)
+{
+ u_int32_t ret;
+
+ memcpy(&ret, p, sizeof(ret));
+ ret = le32toh(ret);
+ return ret;
+}
+
+/**
+ * Convert host byte order to unaligned little endian
+ */
+static inline void htoule32(void *p, u_int32_t v)
+{
+ v = htole32(v);
+ memcpy(p, &v, sizeof(v));
+}
+
+/**
+ * XOR a 32-bit integer into an unaligned destination
+ */
+static inline void xor32u(void *p, u_int32_t x)
+{
+ u_int32_t y;
+
+ memcpy(&y, p, sizeof(y));
+ y ^= x;
+ memcpy(p, &y, sizeof(y));
+}
+
+/**
+ * Multiply two 64-bit words
+ */
+static inline u_int64_t mlt(u_int64_t a, u_int64_t b)
+{
+ return a * b;
+}
+
+/**
+ * Shift a 64-bit unsigned integer v right by n bits, clamp to 32 bit
+*/
+static inline u_int32_t sr(u_int64_t v, u_char n)
+{
+ return v >> n;
+}
+
+/**
+ * Circular left shift by n bits
+ */
+static inline u_int32_t rotl32(u_int32_t v, u_char n)
+{
+ return (v << n) | (v >> (sizeof(v) * 8 - n));
+}
+
+/**
+ * AND two values, using a native integer size >= sizeof(u_int32_t)
+ */
+static inline u_long and(u_long v, u_long mask)
+{
+ return v & mask;
+}
+
+/**
+ * XOR a Chacha20 keystream block into data, increment counter
+ */
+static void chacha_block_xor(private_chapoly_drv_portable_t *this, void *data)
+{
+ u_int32_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf;
+ u_int32_t *out = data;
+ u_int i;
+
+ x0 = this->m[ 0];
+ x1 = this->m[ 1];
+ x2 = this->m[ 2];
+ x3 = this->m[ 3];
+ x4 = this->m[ 4];
+ x5 = this->m[ 5];
+ x6 = this->m[ 6];
+ x7 = this->m[ 7];
+ x8 = this->m[ 8];
+ x9 = this->m[ 9];
+ xa = this->m[10];
+ xb = this->m[11];
+ xc = this->m[12];
+ xd = this->m[13];
+ xe = this->m[14];
+ xf = this->m[15];
+
+ for (i = 0; i < CHACHA_DOUBLEROUNDS; i++)
+ {
+ x0 += x4; xc = rotl32(xc ^ x0, 16);
+ x1 += x5; xd = rotl32(xd ^ x1, 16);
+ x2 += x6; xe = rotl32(xe ^ x2, 16);
+ x3 += x7; xf = rotl32(xf ^ x3, 16);
+
+ x8 += xc; x4 = rotl32(x4 ^ x8, 12);
+ x9 += xd; x5 = rotl32(x5 ^ x9, 12);
+ xa += xe; x6 = rotl32(x6 ^ xa, 12);
+ xb += xf; x7 = rotl32(x7 ^ xb, 12);
+
+ x0 += x4; xc = rotl32(xc ^ x0, 8);
+ x1 += x5; xd = rotl32(xd ^ x1, 8);
+ x2 += x6; xe = rotl32(xe ^ x2, 8);
+ x3 += x7; xf = rotl32(xf ^ x3, 8);
+
+ x8 += xc; x4 = rotl32(x4 ^ x8, 7);
+ x9 += xd; x5 = rotl32(x5 ^ x9, 7);
+ xa += xe; x6 = rotl32(x6 ^ xa, 7);
+ xb += xf; x7 = rotl32(x7 ^ xb, 7);
+
+ x0 += x5; xf = rotl32(xf ^ x0, 16);
+ x1 += x6; xc = rotl32(xc ^ x1, 16);
+ x2 += x7; xd = rotl32(xd ^ x2, 16);
+ x3 += x4; xe = rotl32(xe ^ x3, 16);
+
+ xa += xf; x5 = rotl32(x5 ^ xa, 12);
+ xb += xc; x6 = rotl32(x6 ^ xb, 12);
+ x8 += xd; x7 = rotl32(x7 ^ x8, 12);
+ x9 += xe; x4 = rotl32(x4 ^ x9, 12);
+
+ x0 += x5; xf = rotl32(xf ^ x0, 8);
+ x1 += x6; xc = rotl32(xc ^ x1, 8);
+ x2 += x7; xd = rotl32(xd ^ x2, 8);
+ x3 += x4; xe = rotl32(xe ^ x3, 8);
+
+ xa += xf; x5 = rotl32(x5 ^ xa, 7);
+ xb += xc; x6 = rotl32(x6 ^ xb, 7);
+ x8 += xd; x7 = rotl32(x7 ^ x8, 7);
+ x9 += xe; x4 = rotl32(x4 ^ x9, 7);
+ }
+
+ xor32u(out + 0, le32toh(x0 + this->m[ 0]));
+ xor32u(out + 1, le32toh(x1 + this->m[ 1]));
+ xor32u(out + 2, le32toh(x2 + this->m[ 2]));
+ xor32u(out + 3, le32toh(x3 + this->m[ 3]));
+ xor32u(out + 4, le32toh(x4 + this->m[ 4]));
+ xor32u(out + 5, le32toh(x5 + this->m[ 5]));
+ xor32u(out + 6, le32toh(x6 + this->m[ 6]));
+ xor32u(out + 7, le32toh(x7 + this->m[ 7]));
+ xor32u(out + 8, le32toh(x8 + this->m[ 8]));
+ xor32u(out + 9, le32toh(x9 + this->m[ 9]));
+ xor32u(out + 10, le32toh(xa + this->m[10]));
+ xor32u(out + 11, le32toh(xb + this->m[11]));
+ xor32u(out + 12, le32toh(xc + this->m[12]));
+ xor32u(out + 13, le32toh(xd + this->m[13]));
+ xor32u(out + 14, le32toh(xe + this->m[14]));
+ xor32u(out + 15, le32toh(xf + this->m[15]));
+
+ this->m[CHACHA_BLOCKCOUNT]++;
+}
+
+METHOD(chapoly_drv_t, set_key, bool,
+ private_chapoly_drv_portable_t *this, u_char *constant, u_char *key,
+ u_char *salt)
+{
+ this->m[ 0] = uletoh32(constant + 0);
+ this->m[ 1] = uletoh32(constant + 4);
+ this->m[ 2] = uletoh32(constant + 8);
+ this->m[ 3] = uletoh32(constant + 12);
+
+ this->m[ 4] = uletoh32(key + 0);
+ this->m[ 5] = uletoh32(key + 4);
+ this->m[ 6] = uletoh32(key + 8);
+ this->m[ 7] = uletoh32(key + 12);
+ this->m[ 8] = uletoh32(key + 16);
+ this->m[ 9] = uletoh32(key + 20);
+ this->m[10] = uletoh32(key + 24);
+ this->m[11] = uletoh32(key + 28);
+
+ this->m[CHACHA_NONCE1] = uletoh32(salt);
+
+ return TRUE;
+}
+
+METHOD(chapoly_drv_t, init, bool,
+ private_chapoly_drv_portable_t *this, u_char *iv)
+{
+ u_char key[CHACHA_BLOCK_SIZE];
+
+ this->m[CHACHA_BLOCKCOUNT] = 0;
+ this->m[CHACHA_NONCE2] = uletoh32(iv + 0);
+ this->m[CHACHA_NONCE3] = uletoh32(iv + 4);
+
+ memset(key, 0, CHACHA_BLOCK_SIZE);
+ chacha_block_xor(this, key);
+
+ /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+ this->r[0] = (uletoh32(key + 0) >> 0) & 0x3ffffff;
+ this->r[1] = (uletoh32(key + 3) >> 2) & 0x3ffff03;
+ this->r[2] = (uletoh32(key + 6) >> 4) & 0x3ffc0ff;
+ this->r[3] = (uletoh32(key + 9) >> 6) & 0x3f03fff;
+ this->r[4] = (uletoh32(key + 12) >> 8) & 0x00fffff;
+
+ /* h = 0 */
+ memwipe(this->h, sizeof(this->h));
+
+ this->s[0] = uletoh32(key + 16);
+ this->s[1] = uletoh32(key + 20);
+ this->s[2] = uletoh32(key + 24);
+ this->s[3] = uletoh32(key + 28);
+
+ return TRUE;
+}
+
+METHOD(chapoly_drv_t, poly, bool,
+ private_chapoly_drv_portable_t *this, u_char *data, u_int blocks)
+{
+ u_int32_t r0, r1, r2, r3, r4;
+ u_int32_t s1, s2, s3, s4;
+ u_int32_t h0, h1, h2, h3, h4;
+ u_int64_t d0, d1, d2, d3, d4;
+ u_int i;
+
+ r0 = this->r[0];
+ r1 = this->r[1];
+ r2 = this->r[2];
+ r3 = this->r[3];
+ r4 = this->r[4];
+
+ s1 = r1 * 5;
+ s2 = r2 * 5;
+ s3 = r3 * 5;
+ s4 = r4 * 5;
+
+ h0 = this->h[0];
+ h1 = this->h[1];
+ h2 = this->h[2];
+ h3 = this->h[3];
+ h4 = this->h[4];
+
+ for (i = 0; i < blocks; i++)
+ {
+ /* h += m[i] */
+ h0 += (uletoh32(data + 0) >> 0) & 0x3ffffff;
+ h1 += (uletoh32(data + 3) >> 2) & 0x3ffffff;
+ h2 += (uletoh32(data + 6) >> 4) & 0x3ffffff;
+ h3 += (uletoh32(data + 9) >> 6) & 0x3ffffff;
+ h4 += (uletoh32(data + 12) >> 8) | (1 << 24);
+
+ /* h *= r */
+ d0 = mlt(h0, r0) + mlt(h1, s4) + mlt(h2, s3) + mlt(h3, s2) + mlt(h4, s1);
+ d1 = mlt(h0, r1) + mlt(h1, r0) + mlt(h2, s4) + mlt(h3, s3) + mlt(h4, s2);
+ d2 = mlt(h0, r2) + mlt(h1, r1) + mlt(h2, r0) + mlt(h3, s4) + mlt(h4, s3);
+ d3 = mlt(h0, r3) + mlt(h1, r2) + mlt(h2, r1) + mlt(h3, r0) + mlt(h4, s4);
+ d4 = mlt(h0, r4) + mlt(h1, r3) + mlt(h2, r2) + mlt(h3, r1) + mlt(h4, r0);
+
+ /* (partial) h %= p */
+ d1 += sr(d0, 26); h0 = and(d0, 0x3ffffff);
+ d2 += sr(d1, 26); h1 = and(d1, 0x3ffffff);
+ d3 += sr(d2, 26); h2 = and(d2, 0x3ffffff);
+ d4 += sr(d3, 26); h3 = and(d3, 0x3ffffff);
+ h0 += sr(d4, 26) * 5; h4 = and(d4, 0x3ffffff);
+ h1 += h0 >> 26; h0 = h0 & 0x3ffffff;
+
+ data += POLY_BLOCK_SIZE;
+ }
+
+ this->h[0] = h0;
+ this->h[1] = h1;
+ this->h[2] = h2;
+ this->h[3] = h3;
+ this->h[4] = h4;
+
+ return TRUE;
+}
+
+METHOD(chapoly_drv_t, chacha, bool,
+ private_chapoly_drv_portable_t *this, u_char *stream)
+{
+ memset(stream, 0, CHACHA_BLOCK_SIZE);
+ chacha_block_xor(this, stream);
+
+ return TRUE;
+}
+
+METHOD(chapoly_drv_t, encrypt, bool,
+ private_chapoly_drv_portable_t *this, u_char *data, u_int blocks)
+{
+ u_int i;
+
+ for (i = 0; i < blocks; i++)
+ {
+ chacha_block_xor(this, data);
+ poly(this, data, 4);
+ data += CHACHA_BLOCK_SIZE;
+ }
+ return TRUE;
+}
+
+METHOD(chapoly_drv_t, decrypt, bool,
+ private_chapoly_drv_portable_t *this, u_char *data, u_int blocks)
+{
+ u_int i;
+
+ for (i = 0; i < blocks; i++)
+ {
+ poly(this, data, 4);
+ chacha_block_xor(this, data);
+ data += CHACHA_BLOCK_SIZE;
+ }
+ return TRUE;
+}
+
+METHOD(chapoly_drv_t, finish, bool,
+ private_chapoly_drv_portable_t *this, u_char *mac)
+{
+ u_int32_t h0, h1, h2, h3, h4;
+ u_int32_t g0, g1, g2, g3, g4;
+ u_int32_t mask;
+ u_int64_t f = 0;
+
+ /* fully carry h */
+ h0 = this->h[0];
+ h1 = this->h[1];
+ h2 = this->h[2];
+ h3 = this->h[3];
+ h4 = this->h[4];
+
+ h2 += (h1 >> 26); h1 = h1 & 0x3ffffff;
+ h3 += (h2 >> 26); h2 = h2 & 0x3ffffff;
+ h4 += (h3 >> 26); h3 = h3 & 0x3ffffff;
+ h0 += (h4 >> 26) * 5; h4 = h4 & 0x3ffffff;
+ h1 += (h0 >> 26); h0 = h0 & 0x3ffffff;
+
+ /* compute h + -p */
+ g0 = h0 + 5;
+ g1 = h1 + (g0 >> 26); g0 &= 0x3ffffff;
+ g2 = h2 + (g1 >> 26); g1 &= 0x3ffffff;
+ g3 = h3 + (g2 >> 26); g2 &= 0x3ffffff;
+ g4 = h4 + (g3 >> 26) - (1 << 26); g3 &= 0x3ffffff;
+
+ /* select h if h < p, or h + -p if h >= p */
+ mask = (g4 >> ((sizeof(u_int32_t) * 8) - 1)) - 1;
+ g0 &= mask;
+ g1 &= mask;
+ g2 &= mask;
+ g3 &= mask;
+ g4 &= mask;
+ mask = ~mask;
+ h0 = (h0 & mask) | g0;
+ h1 = (h1 & mask) | g1;
+ h2 = (h2 & mask) | g2;
+ h3 = (h3 & mask) | g3;
+ h4 = (h4 & mask) | g4;
+
+ /* h = h % (2^128) */
+ h0 = (h0 >> 0) | (h1 << 26);
+ h1 = (h1 >> 6) | (h2 << 20);
+ h2 = (h2 >> 12) | (h3 << 14);
+ h3 = (h3 >> 18) | (h4 << 8);
+
+ /* mac = (h + s) % (2^128) */
+ f = (f >> 32) + h0 + this->s[0]; htoule32(mac + 0, f);
+ f = (f >> 32) + h1 + this->s[1]; htoule32(mac + 4, f);
+ f = (f >> 32) + h2 + this->s[2]; htoule32(mac + 8, f);
+ f = (f >> 32) + h3 + this->s[3]; htoule32(mac + 12, f);
+
+ return TRUE;
+}
+
+METHOD(chapoly_drv_t, destroy, void,
+ private_chapoly_drv_portable_t *this)
+{
+ memwipe(this->m, sizeof(this->m));
+ memwipe(this->h, sizeof(this->h));
+ memwipe(this->r, sizeof(this->r));
+ memwipe(this->s, sizeof(this->s));
+ free(this);
+}
+
+/**
+ * See header
+ */
+chapoly_drv_t *chapoly_drv_portable_create()
+{
+ private_chapoly_drv_portable_t *this;
+
+ INIT(this,
+ .public = {
+ .set_key = _set_key,
+ .init = _init,
+ .poly = _poly,
+ .chacha = _chacha,
+ .encrypt = _encrypt,
+ .decrypt = _decrypt,
+ .finish = _finish,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/plugins/chapoly/chapoly_drv_portable.h b/src/libstrongswan/plugins/chapoly/chapoly_drv_portable.h
new file mode 100644
index 000000000..a320b2d41
--- /dev/null
+++ b/src/libstrongswan/plugins/chapoly/chapoly_drv_portable.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup chapoly_drv_portable chapoly_drv_portable
+ * @{ @ingroup chapoly
+ */
+
+#include "chapoly_drv.h"
+
+#ifndef CHAPOLY_DRV_PORTABLE_H_
+#define CHAPOLY_DRV_PORTABLE_H_
+
+/**
+ * Create a chapoly_drv_portable instance.
+ */
+chapoly_drv_t *chapoly_drv_portable_create();
+
+#endif /** CHAPOLY_drv_PORTABLE_H_ @}*/
diff --git a/src/libstrongswan/plugins/chapoly/chapoly_drv_ssse3.c b/src/libstrongswan/plugins/chapoly/chapoly_drv_ssse3.c
new file mode 100644
index 000000000..df88e7d77
--- /dev/null
+++ b/src/libstrongswan/plugins/chapoly/chapoly_drv_ssse3.c
@@ -0,0 +1,867 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * Based on public domain code by Andrew Moon and Daniel J. Bernstein.
+ *
+ * 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 "chapoly_drv_ssse3.h"
+
+#ifdef __SSSE3__
+
+#include <utils/cpu_feature.h>
+
+#include <tmmintrin.h>
+
+#define CHACHA_DOUBLEROUNDS 10
+
+typedef struct private_chapoly_drv_ssse3_t private_chapoly_drv_ssse3_t;
+
+/**
+ * Private data of an chapoly_drv_ssse3_t object.
+ */
+struct private_chapoly_drv_ssse3_t {
+
+ /**
+ * Public chapoly_drv_ssse3_t interface.
+ */
+ chapoly_drv_t public;
+
+ /**
+ * ChaCha20 state matrix, as 128-bit vectors
+ */
+ __m128i m[4];
+
+ /**
+ * Poly1305 update key
+ */
+ u_int32_t r[5];
+
+ /**
+ * Poly1305 update key r^2
+ */
+ u_int32_t u[5];
+
+ /**
+ * Poly1305 state
+ */
+ u_int32_t h[5];
+
+ /**
+ * Poly1305 finalize key
+ */
+ u_int32_t s[4];
+};
+
+/**
+ * Read a 32-bit integer from an unaligned address
+ */
+static inline u_int32_t ru32(void *p)
+{
+ u_int32_t ret;
+
+ memcpy(&ret, p, sizeof(ret));
+ return ret;
+}
+
+/**
+ * Write a 32-bit word to an unaligned address
+ */
+static inline void wu32(void *p, u_int32_t v)
+{
+ memcpy(p, &v, sizeof(v));
+}
+
+/**
+ * Shift a 64-bit unsigned integer v right by n bits, clamp to 32 bit
+*/
+static inline u_int32_t sr(u_int64_t v, u_char n)
+{
+ return v >> n;
+}
+
+/**
+ * AND two values, using a native integer size >= sizeof(u_int32_t)
+ */
+static inline u_long and(u_long v, u_long mask)
+{
+ return v & mask;
+}
+
+/**
+ * r = shuffle(a ^ b, s)
+ */
+static inline __m128i sfflxor32(__m128i a, __m128i b, __m128i s)
+{
+ return _mm_shuffle_epi8(_mm_xor_si128(a, b), s);
+}
+
+/**
+ * r = rotl32(a ^ b, r)
+ */
+static inline __m128i rotlxor32(__m128i a, __m128i b, u_char r)
+{
+ a = _mm_xor_si128(a, b);
+ return _mm_or_si128(_mm_slli_epi32(a, r), _mm_srli_epi32(a, 32 - r));
+}
+
+/**
+ * XOR a Chacha20 keystream block into data, increment counter
+ */
+static void chacha_block_xor(private_chapoly_drv_ssse3_t *this, void *data)
+{
+ __m128i x0, x1, x2, x3, r8, r16, *out = data;
+ u_int i;
+
+ r8 = _mm_set_epi8(14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3);
+ r16 = _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2);
+
+ x0 = this->m[0];
+ x1 = this->m[1];
+ x2 = this->m[2];
+ x3 = this->m[3];
+
+ for (i = 0 ; i < CHACHA_DOUBLEROUNDS; i++)
+ {
+ x0 = _mm_add_epi32(x0, x1);
+ x3 = sfflxor32(x3, x0, r16);
+
+ x2 = _mm_add_epi32(x2, x3);
+ x1 = rotlxor32(x1, x2, 12);
+
+ x0 = _mm_add_epi32(x0, x1);
+ x3 = sfflxor32(x3, x0, r8);
+
+ x2 = _mm_add_epi32(x2, x3);
+ x1 = rotlxor32(x1, x2, 7);
+
+ x1 = _mm_shuffle_epi32(x1, _MM_SHUFFLE(0, 3, 2, 1));
+ x2 = _mm_shuffle_epi32(x2, _MM_SHUFFLE(1, 0, 3, 2));
+ x3 = _mm_shuffle_epi32(x3, _MM_SHUFFLE(2, 1, 0, 3));
+
+ x0 = _mm_add_epi32(x0, x1);
+ x3 = sfflxor32(x3, x0, r16);
+
+ x2 = _mm_add_epi32(x2, x3);
+ x1 = rotlxor32(x1, x2, 12);
+
+ x0 = _mm_add_epi32(x0, x1);
+ x3 = sfflxor32(x3, x0, r8);
+
+ x2 = _mm_add_epi32(x2, x3);
+ x1 = rotlxor32(x1, x2, 7);
+
+ x1 = _mm_shuffle_epi32(x1, _MM_SHUFFLE(2, 1, 0, 3));
+ x2 = _mm_shuffle_epi32(x2, _MM_SHUFFLE(1, 0, 3, 2));
+ x3 = _mm_shuffle_epi32(x3, _MM_SHUFFLE(0, 3, 2, 1));
+ }
+
+ x0 = _mm_add_epi32(x0, this->m[0]);
+ x1 = _mm_add_epi32(x1, this->m[1]);
+ x2 = _mm_add_epi32(x2, this->m[2]);
+ x3 = _mm_add_epi32(x3, this->m[3]);
+ x0 = _mm_xor_si128(x0, _mm_loadu_si128(out + 0));
+ x1 = _mm_xor_si128(x1, _mm_loadu_si128(out + 1));
+ x2 = _mm_xor_si128(x2, _mm_loadu_si128(out + 2));
+ x3 = _mm_xor_si128(x3, _mm_loadu_si128(out + 3));
+ _mm_storeu_si128(out + 0, x0);
+ _mm_storeu_si128(out + 1, x1);
+ _mm_storeu_si128(out + 2, x2);
+ _mm_storeu_si128(out + 3, x3);
+
+ this->m[3] = _mm_add_epi32(this->m[3], _mm_set_epi32(0, 0, 0, 1));
+}
+
+/**
+ * XOR four Chacha20 keystream blocks into data, increment counter
+ */
+static void chacha_4block_xor(private_chapoly_drv_ssse3_t *this, void *data)
+{
+ __m128i x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, xa, xb, xc, xd, xe, xf;
+ __m128i r8, r16, ctrinc, t, *out = data;
+ u_int32_t *m = (u_int32_t*)this->m;
+ u_int i;
+
+ r8 = _mm_set_epi8(14, 13, 12, 15, 10, 9, 8, 11, 6, 5, 4, 7, 2, 1, 0, 3);
+ r16 = _mm_set_epi8(13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2);
+ ctrinc = _mm_set_epi32(3, 2, 1, 0);
+
+ x0 = _mm_set1_epi32(m[ 0]);
+ x1 = _mm_set1_epi32(m[ 1]);
+ x2 = _mm_set1_epi32(m[ 2]);
+ x3 = _mm_set1_epi32(m[ 3]);
+ x4 = _mm_set1_epi32(m[ 4]);
+ x5 = _mm_set1_epi32(m[ 5]);
+ x6 = _mm_set1_epi32(m[ 6]);
+ x7 = _mm_set1_epi32(m[ 7]);
+ x8 = _mm_set1_epi32(m[ 8]);
+ x9 = _mm_set1_epi32(m[ 9]);
+ xa = _mm_set1_epi32(m[10]);
+ xb = _mm_set1_epi32(m[11]);
+ xc = _mm_set1_epi32(m[12]);
+ xd = _mm_set1_epi32(m[13]);
+ xe = _mm_set1_epi32(m[14]);
+ xf = _mm_set1_epi32(m[15]);
+
+ xc = _mm_add_epi32(xc, ctrinc);
+
+ for (i = 0 ; i < CHACHA_DOUBLEROUNDS; i++)
+ {
+ x0 = _mm_add_epi32(x0, x4); xc = sfflxor32(xc, x0, r16);
+ x1 = _mm_add_epi32(x1, x5); xd = sfflxor32(xd, x1, r16);
+ x2 = _mm_add_epi32(x2, x6); xe = sfflxor32(xe, x2, r16);
+ x3 = _mm_add_epi32(x3, x7); xf = sfflxor32(xf, x3, r16);
+
+ x8 = _mm_add_epi32(x8, xc); x4 = rotlxor32(x4, x8, 12);
+ x9 = _mm_add_epi32(x9, xd); x5 = rotlxor32(x5, x9, 12);
+ xa = _mm_add_epi32(xa, xe); x6 = rotlxor32(x6, xa, 12);
+ xb = _mm_add_epi32(xb, xf); x7 = rotlxor32(x7, xb, 12);
+
+ x0 = _mm_add_epi32(x0, x4); xc = sfflxor32(xc, x0, r8);
+ x1 = _mm_add_epi32(x1, x5); xd = sfflxor32(xd, x1, r8);
+ x2 = _mm_add_epi32(x2, x6); xe = sfflxor32(xe, x2, r8);
+ x3 = _mm_add_epi32(x3, x7); xf = sfflxor32(xf, x3, r8);
+
+ x8 = _mm_add_epi32(x8, xc); x4 = rotlxor32(x4, x8, 7);
+ x9 = _mm_add_epi32(x9, xd); x5 = rotlxor32(x5, x9, 7);
+ xa = _mm_add_epi32(xa, xe); x6 = rotlxor32(x6, xa, 7);
+ xb = _mm_add_epi32(xb, xf); x7 = rotlxor32(x7, xb, 7);
+
+ x0 = _mm_add_epi32(x0, x5); xf = sfflxor32(xf, x0, r16);
+ x1 = _mm_add_epi32(x1, x6); xc = sfflxor32(xc, x1, r16);
+ x2 = _mm_add_epi32(x2, x7); xd = sfflxor32(xd, x2, r16);
+ x3 = _mm_add_epi32(x3, x4); xe = sfflxor32(xe, x3, r16);
+
+ xa = _mm_add_epi32(xa, xf); x5 = rotlxor32(x5, xa, 12);
+ xb = _mm_add_epi32(xb, xc); x6 = rotlxor32(x6, xb, 12);
+ x8 = _mm_add_epi32(x8, xd); x7 = rotlxor32(x7, x8, 12);
+ x9 = _mm_add_epi32(x9, xe); x4 = rotlxor32(x4, x9, 12);
+
+ x0 = _mm_add_epi32(x0, x5); xf = sfflxor32(xf, x0, r8);
+ x1 = _mm_add_epi32(x1, x6); xc = sfflxor32(xc, x1, r8);
+ x2 = _mm_add_epi32(x2, x7); xd = sfflxor32(xd, x2, r8);
+ x3 = _mm_add_epi32(x3, x4); xe = sfflxor32(xe, x3, r8);
+
+ xa = _mm_add_epi32(xa, xf); x5 = rotlxor32(x5, xa, 7);
+ xb = _mm_add_epi32(xb, xc); x6 = rotlxor32(x6, xb, 7);
+ x8 = _mm_add_epi32(x8, xd); x7 = rotlxor32(x7, x8, 7);
+ x9 = _mm_add_epi32(x9, xe); x4 = rotlxor32(x4, x9, 7);
+ }
+
+ x0 = _mm_add_epi32(x0, _mm_set1_epi32(m[ 0]));
+ x1 = _mm_add_epi32(x1, _mm_set1_epi32(m[ 1]));
+ x2 = _mm_add_epi32(x2, _mm_set1_epi32(m[ 2]));
+ x3 = _mm_add_epi32(x3, _mm_set1_epi32(m[ 3]));
+ x4 = _mm_add_epi32(x4, _mm_set1_epi32(m[ 4]));
+ x5 = _mm_add_epi32(x5, _mm_set1_epi32(m[ 5]));
+ x6 = _mm_add_epi32(x6, _mm_set1_epi32(m[ 6]));
+ x7 = _mm_add_epi32(x7, _mm_set1_epi32(m[ 7]));
+ x8 = _mm_add_epi32(x8, _mm_set1_epi32(m[ 8]));
+ x9 = _mm_add_epi32(x9, _mm_set1_epi32(m[ 9]));
+ xa = _mm_add_epi32(xa, _mm_set1_epi32(m[10]));
+ xb = _mm_add_epi32(xb, _mm_set1_epi32(m[11]));
+ xc = _mm_add_epi32(xc, _mm_set1_epi32(m[12]));
+ xd = _mm_add_epi32(xd, _mm_set1_epi32(m[13]));
+ xe = _mm_add_epi32(xe, _mm_set1_epi32(m[14]));
+ xf = _mm_add_epi32(xf, _mm_set1_epi32(m[15]));
+
+ xc = _mm_add_epi32(xc, ctrinc);
+
+ /* transpose state matrix by interleaving 32-, then 64-bit words */
+ t = x0; x0 = _mm_unpacklo_epi32(t, x1);
+ x1 = _mm_unpackhi_epi32(t, x1);
+ t = x2; x2 = _mm_unpacklo_epi32(t, x3);
+ x3 = _mm_unpackhi_epi32(t, x3);
+ t = x4; x4 = _mm_unpacklo_epi32(t, x5);
+ x5 = _mm_unpackhi_epi32(t, x5);
+ t = x6; x6 = _mm_unpacklo_epi32(t, x7);
+ x7 = _mm_unpackhi_epi32(t, x7);
+ t = x8; x8 = _mm_unpacklo_epi32(t, x9);
+ x9 = _mm_unpackhi_epi32(t, x9);
+ t = xa; xa = _mm_unpacklo_epi32(t, xb);
+ xb = _mm_unpackhi_epi32(t, xb);
+ t = xc; xc = _mm_unpacklo_epi32(t, xd);
+ xd = _mm_unpackhi_epi32(t, xd);
+ t = xe; xe = _mm_unpacklo_epi32(t, xf);
+ xf = _mm_unpackhi_epi32(t, xf);
+
+ t = x0; x0 = _mm_unpacklo_epi64(t, x2);
+ x2 = _mm_unpackhi_epi64(t, x2);
+ t = x1; x1 = _mm_unpacklo_epi64(t, x3);
+ x3 = _mm_unpackhi_epi64(t, x3);
+ t = x4; x4 = _mm_unpacklo_epi64(t, x6);
+ x6 = _mm_unpackhi_epi64(t, x6);
+ t = x5; x5 = _mm_unpacklo_epi64(t, x7);
+ x7 = _mm_unpackhi_epi64(t, x7);
+ t = x8; x8 = _mm_unpacklo_epi64(t, xa);
+ xa = _mm_unpackhi_epi64(t, xa);
+ t = x9; x9 = _mm_unpacklo_epi64(t, xb);
+ xb = _mm_unpackhi_epi64(t, xb);
+ t = xc; xc = _mm_unpacklo_epi64(t, xe);
+ xe = _mm_unpackhi_epi64(t, xe);
+ t = xd; xd = _mm_unpacklo_epi64(t, xf);
+ xf = _mm_unpackhi_epi64(t, xf);
+
+ x0 = _mm_xor_si128(_mm_loadu_si128(out + 0), x0);
+ x1 = _mm_xor_si128(_mm_loadu_si128(out + 8), x1);
+ x2 = _mm_xor_si128(_mm_loadu_si128(out + 4), x2);
+ x3 = _mm_xor_si128(_mm_loadu_si128(out + 12), x3);
+ x4 = _mm_xor_si128(_mm_loadu_si128(out + 1), x4);
+ x5 = _mm_xor_si128(_mm_loadu_si128(out + 9), x5);
+ x6 = _mm_xor_si128(_mm_loadu_si128(out + 5), x6);
+ x7 = _mm_xor_si128(_mm_loadu_si128(out + 13), x7);
+ x8 = _mm_xor_si128(_mm_loadu_si128(out + 2), x8);
+ x9 = _mm_xor_si128(_mm_loadu_si128(out + 10), x9);
+ xa = _mm_xor_si128(_mm_loadu_si128(out + 6), xa);
+ xb = _mm_xor_si128(_mm_loadu_si128(out + 14), xb);
+ xc = _mm_xor_si128(_mm_loadu_si128(out + 3), xc);
+ xd = _mm_xor_si128(_mm_loadu_si128(out + 11), xd);
+ xe = _mm_xor_si128(_mm_loadu_si128(out + 7), xe);
+ xf = _mm_xor_si128(_mm_loadu_si128(out + 15), xf);
+
+ _mm_storeu_si128(out + 0, x0);
+ _mm_storeu_si128(out + 8, x1);
+ _mm_storeu_si128(out + 4, x2);
+ _mm_storeu_si128(out + 12, x3);
+ _mm_storeu_si128(out + 1, x4);
+ _mm_storeu_si128(out + 9, x5);
+ _mm_storeu_si128(out + 5, x6);
+ _mm_storeu_si128(out + 13, x7);
+ _mm_storeu_si128(out + 2, x8);
+ _mm_storeu_si128(out + 10, x9);
+ _mm_storeu_si128(out + 6, xa);
+ _mm_storeu_si128(out + 14, xb);
+ _mm_storeu_si128(out + 3, xc);
+ _mm_storeu_si128(out + 11, xd);
+ _mm_storeu_si128(out + 7, xe);
+ _mm_storeu_si128(out + 15, xf);
+
+ this->m[3] = _mm_add_epi32(this->m[3], _mm_set_epi32(0, 0, 0, 4));
+}
+
+METHOD(chapoly_drv_t, set_key, bool,
+ private_chapoly_drv_ssse3_t *this, u_char *constant, u_char *key,
+ u_char *salt)
+{
+ this->m[0] = _mm_loadu_si128((__m128i*)constant);
+ this->m[1] = _mm_loadu_si128((__m128i*)key + 0);
+ this->m[2] = _mm_loadu_si128((__m128i*)key + 1);
+ this->m[3] = _mm_set_epi32(0, 0, ru32(salt), 0);
+
+ return TRUE;
+}
+
+/**
+ * r[127:64] = h[95:64] * a, r[63:0] = h[31:0] * b
+ */
+static inline __m128i mul2(__m128i h, u_int32_t a, u_int32_t b)
+{
+ return _mm_mul_epu32(h, _mm_set_epi32(0, a, 0, b));
+}
+
+/**
+ * c = a[127:64] + a[63:0] + b[127:64] + b[63:0]
+ * z = x[127:64] + x[63:0] + y[127:64] + y[63:0]
+ */
+static inline void sum2(__m128i a, __m128i b, __m128i x, __m128i y,
+ u_int64_t *c, u_int64_t *z)
+{
+ __m128i r, s;
+
+ a = _mm_add_epi64(a, b);
+ x = _mm_add_epi64(x, y);
+ r = _mm_unpacklo_epi64(x, a);
+ s = _mm_unpackhi_epi64(x, a);
+ r = _mm_add_epi64(r, s);
+
+ _mm_storel_epi64((__m128i*)z, r);
+ _mm_storel_epi64((__m128i*)c, _mm_srli_si128(r, 8));
+}
+
+/**
+ * r = a[127:64] + b[127:64] + c[127:64] + d[127:64] + e[127:64]
+ * + a[63:0] + b[63:0] + c[63:0] + d[63:0] + e[63:0]
+ */
+static inline u_int64_t sum5(__m128i a, __m128i b, __m128i c,
+ __m128i d, __m128i e)
+{
+ u_int64_t r;
+
+ a = _mm_add_epi64(a, b);
+ c = _mm_add_epi64(c, d);
+ a = _mm_add_epi64(a, e);
+ a = _mm_add_epi64(a, c);
+
+ a = _mm_add_epi64(a, _mm_srli_si128(a, 8));
+ _mm_storel_epi64((__m128i*)&r, a);
+
+ return r;
+}
+
+/**
+ * Make second Poly1305 key u = r^2
+ */
+static void make_u(private_chapoly_drv_ssse3_t *this)
+{
+ __m128i r01, r23, r44, x0, x1, y0, y1, z0;
+ u_int32_t r0, r1, r2, r3, r4;
+ u_int32_t u0, u1, u2, u3, u4;
+ u_int32_t s1, s2, s3, s4;
+ u_int64_t d0, d1, d2, d3, d4;
+
+ r0 = this->r[0];
+ r1 = this->r[1];
+ r2 = this->r[2];
+ r3 = this->r[3];
+ r4 = this->r[4];
+
+ s1 = r1 * 5;
+ s2 = r2 * 5;
+ s3 = r3 * 5;
+ s4 = r4 * 5;
+
+ r01 = _mm_set_epi32(0, r0, 0, r1);
+ r23 = _mm_set_epi32(0, r2, 0, r3);
+ r44 = _mm_set_epi32(0, r4, 0, r4);
+
+ /* u = r^2 */
+ x0 = mul2(r01, r0, s4);
+ x1 = mul2(r01, r1, r0);
+ y0 = mul2(r23, s3, s2);
+ y1 = mul2(r23, s4, s3);
+ z0 = mul2(r44, s1, s2);
+ y0 = _mm_add_epi64(y0, _mm_srli_si128(z0, 8));
+ y1 = _mm_add_epi64(y1, _mm_slli_si128(z0, 8));
+ sum2(x0, y0, x1, y1, &d0, &d1);
+
+ x0 = mul2(r01, r2, r1);
+ x1 = mul2(r01, r3, r2);
+ y0 = mul2(r23, r0, s4);
+ y1 = mul2(r23, r1, r0);
+ z0 = mul2(r44, s3, s4);
+ y0 = _mm_add_epi64(y0, _mm_srli_si128(z0, 8));
+ y1 = _mm_add_epi64(y1, _mm_slli_si128(z0, 8));
+ sum2(x0, y0, x1, y1, &d2, &d3);
+
+ x0 = mul2(r01, r4, r3);
+ y0 = mul2(r23, r2, r1);
+ z0 = mul2(r44, r0, 0);
+ y0 = _mm_add_epi64(y0, z0);
+ x0 = _mm_add_epi64(x0, y0);
+ x0 = _mm_add_epi64(x0, _mm_srli_si128(x0, 8));
+ _mm_storel_epi64((__m128i*)&d4, x0);
+
+ /* (partial) r %= p */
+ d1 += sr(d0, 26); u0 = and(d0, 0x3ffffff);
+ d2 += sr(d1, 26); u1 = and(d1, 0x3ffffff);
+ d3 += sr(d2, 26); u2 = and(d2, 0x3ffffff);
+ d4 += sr(d3, 26); u3 = and(d3, 0x3ffffff);
+ u0 += sr(d4, 26) * 5; u4 = and(d4, 0x3ffffff);
+ u1 += u0 >> 26; u0 &= 0x3ffffff;
+
+ this->u[0] = u0;
+ this->u[1] = u1;
+ this->u[2] = u2;
+ this->u[3] = u3;
+ this->u[4] = u4;
+}
+
+METHOD(chapoly_drv_t, init, bool,
+ private_chapoly_drv_ssse3_t *this, u_char *iv)
+{
+ u_char key[CHACHA_BLOCK_SIZE];
+
+ this->m[3] = _mm_or_si128(
+ _mm_set_epi32(ru32(iv + 4), ru32(iv + 0), 0, 0),
+ _mm_and_si128(this->m[3], _mm_set_epi32(0, 0, ~0, 0)));
+
+ memset(key, 0, CHACHA_BLOCK_SIZE);
+ chacha_block_xor(this, key);
+
+ /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
+ this->r[0] = (ru32(key + 0) >> 0) & 0x3ffffff;
+ this->r[1] = (ru32(key + 3) >> 2) & 0x3ffff03;
+ this->r[2] = (ru32(key + 6) >> 4) & 0x3ffc0ff;
+ this->r[3] = (ru32(key + 9) >> 6) & 0x3f03fff;
+ this->r[4] = (ru32(key + 12) >> 8) & 0x00fffff;
+
+ make_u(this);
+
+ /* h = 0 */
+ memwipe(this->h, sizeof(this->h));
+
+ this->s[0] = ru32(key + 16);
+ this->s[1] = ru32(key + 20);
+ this->s[2] = ru32(key + 24);
+ this->s[3] = ru32(key + 28);
+
+ return TRUE;
+}
+
+/**
+ * Update Poly1305 for a multiple of two blocks
+ */
+static void poly2(private_chapoly_drv_ssse3_t *this, u_char *data, u_int dblks)
+{
+ u_int32_t r0, r1, r2, r3, r4, u0, u1, u2, u3, u4;
+ u_int32_t s1, s2, s3, s4, v1, v2, v3, v4;
+ __m128i hc0, hc1, hc2, hc3, hc4;
+ u_int32_t h0, h1, h2, h3, h4;
+ u_int32_t c0, c1, c2, c3, c4;
+ u_int64_t d0, d1, d2, d3, d4;
+ u_int i;
+
+ r0 = this->r[0];
+ r1 = this->r[1];
+ r2 = this->r[2];
+ r3 = this->r[3];
+ r4 = this->r[4];
+
+ s1 = r1 * 5;
+ s2 = r2 * 5;
+ s3 = r3 * 5;
+ s4 = r4 * 5;
+
+ u0 = this->u[0];
+ u1 = this->u[1];
+ u2 = this->u[2];
+ u3 = this->u[3];
+ u4 = this->u[4];
+
+ v1 = u1 * 5;
+ v2 = u2 * 5;
+ v3 = u3 * 5;
+ v4 = u4 * 5;
+
+ h0 = this->h[0];
+ h1 = this->h[1];
+ h2 = this->h[2];
+ h3 = this->h[3];
+ h4 = this->h[4];
+
+ /* h = (h + c1) * r^2 + c2 * r */
+ for (i = 0; i < dblks; i++)
+ {
+ /* h += m[i] */
+ h0 += (ru32(data + 0) >> 0) & 0x3ffffff;
+ h1 += (ru32(data + 3) >> 2) & 0x3ffffff;
+ h2 += (ru32(data + 6) >> 4) & 0x3ffffff;
+ h3 += (ru32(data + 9) >> 6) & 0x3ffffff;
+ h4 += (ru32(data + 12) >> 8) | (1 << 24);
+ data += POLY_BLOCK_SIZE;
+
+ /* c = m[i + 1] */
+ c0 = (ru32(data + 0) >> 0) & 0x3ffffff;
+ c1 = (ru32(data + 3) >> 2) & 0x3ffffff;
+ c2 = (ru32(data + 6) >> 4) & 0x3ffffff;
+ c3 = (ru32(data + 9) >> 6) & 0x3ffffff;
+ c4 = (ru32(data + 12) >> 8) | (1 << 24);
+ data += POLY_BLOCK_SIZE;
+
+ hc0 = _mm_set_epi32(0, h0, 0, c0);
+ hc1 = _mm_set_epi32(0, h1, 0, c1);
+ hc2 = _mm_set_epi32(0, h2, 0, c2);
+ hc3 = _mm_set_epi32(0, h3, 0, c3);
+ hc4 = _mm_set_epi32(0, h4, 0, c4);
+
+ /* h = h * r^2 + c * r */
+ d0 = sum5(mul2(hc0, u0, r0),
+ mul2(hc1, v4, s4),
+ mul2(hc2, v3, s3),
+ mul2(hc3, v2, s2),
+ mul2(hc4, v1, s1));
+ d1 = sum5(mul2(hc0, u1, r1),
+ mul2(hc1, u0, r0),
+ mul2(hc2, v4, s4),
+ mul2(hc3, v3, s3),
+ mul2(hc4, v2, s2));
+ d2 = sum5(mul2(hc0, u2, r2),
+ mul2(hc1, u1, r1),
+ mul2(hc2, u0, r0),
+ mul2(hc3, v4, s4),
+ mul2(hc4, v3, s3));
+ d3 = sum5(mul2(hc0, u3, r3),
+ mul2(hc1, u2, r2),
+ mul2(hc2, u1, r1),
+ mul2(hc3, u0, r0),
+ mul2(hc4, v4, s4));
+ d4 = sum5(mul2(hc0, u4, r4),
+ mul2(hc1, u3, r3),
+ mul2(hc2, u2, r2),
+ mul2(hc3, u1, r1),
+ mul2(hc4, u0, r0));
+
+ /* (partial) h %= p */
+ d1 += sr(d0, 26); h0 = and(d0, 0x3ffffff);
+ d2 += sr(d1, 26); h1 = and(d1, 0x3ffffff);
+ d3 += sr(d2, 26); h2 = and(d2, 0x3ffffff);
+ d4 += sr(d3, 26); h3 = and(d3, 0x3ffffff);
+ h0 += sr(d4, 26) * 5; h4 = and(d4, 0x3ffffff);
+ h1 += h0 >> 26; h0 = h0 & 0x3ffffff;
+ }
+
+ this->h[0] = h0;
+ this->h[1] = h1;
+ this->h[2] = h2;
+ this->h[3] = h3;
+ this->h[4] = h4;
+}
+
+/**
+ * Update Poly1305 for a single block
+ */
+static void poly1(private_chapoly_drv_ssse3_t *this, u_char *data)
+{
+ u_int32_t r0, r1, r2, r3, r4;
+ u_int32_t s1, s2, s3, s4;
+ u_int32_t h0, h1, h2, h3, h4;
+ u_int64_t d0, d1, d2, d3, d4;
+ __m128i h01, h23, h44;
+ __m128i x0, x1, y0, y1, z0;
+ u_int32_t t0, t1;
+
+ r0 = this->r[0];
+ r1 = this->r[1];
+ r2 = this->r[2];
+ r3 = this->r[3];
+ r4 = this->r[4];
+
+ s1 = r1 * 5;
+ s2 = r2 * 5;
+ s3 = r3 * 5;
+ s4 = r4 * 5;
+
+ h0 = this->h[0];
+ h1 = this->h[1];
+ h2 = this->h[2];
+ h3 = this->h[3];
+ h4 = this->h[4];
+
+ h01 = _mm_set_epi32(0, h0, 0, h1);
+ h23 = _mm_set_epi32(0, h2, 0, h3);
+ h44 = _mm_set_epi32(0, h4, 0, h4);
+
+ /* h += m[i] */
+ t0 = (ru32(data + 0) >> 0) & 0x3ffffff;
+ t1 = (ru32(data + 3) >> 2) & 0x3ffffff;
+ h01 = _mm_add_epi32(h01, _mm_set_epi32(0, t0, 0, t1));
+ t0 = (ru32(data + 6) >> 4) & 0x3ffffff;
+ t1 = (ru32(data + 9) >> 6) & 0x3ffffff;
+ h23 = _mm_add_epi32(h23, _mm_set_epi32(0, t0, 0, t1));
+ t0 = (ru32(data + 12) >> 8) | (1 << 24);
+ h44 = _mm_add_epi32(h44, _mm_set_epi32(0, t0, 0, t0));
+
+ /* h *= r */
+ x0 = mul2(h01, r0, s4);
+ x1 = mul2(h01, r1, r0);
+ y0 = mul2(h23, s3, s2);
+ y1 = mul2(h23, s4, s3);
+ z0 = mul2(h44, s1, s2);
+ y0 = _mm_add_epi64(y0, _mm_srli_si128(z0, 8));
+ y1 = _mm_add_epi64(y1, _mm_slli_si128(z0, 8));
+ sum2(x0, y0, x1, y1, &d0, &d1);
+
+ x0 = mul2(h01, r2, r1);
+ x1 = mul2(h01, r3, r2);
+ y0 = mul2(h23, r0, s4);
+ y1 = mul2(h23, r1, r0);
+ z0 = mul2(h44, s3, s4);
+ y0 = _mm_add_epi64(y0, _mm_srli_si128(z0, 8));
+ y1 = _mm_add_epi64(y1, _mm_slli_si128(z0, 8));
+ sum2(x0, y0, x1, y1, &d2, &d3);
+
+ x0 = mul2(h01, r4, r3);
+ y0 = mul2(h23, r2, r1);
+ z0 = mul2(h44, r0, 0);
+ y0 = _mm_add_epi64(y0, z0);
+ x0 = _mm_add_epi64(x0, y0);
+ x0 = _mm_add_epi64(x0, _mm_srli_si128(x0, 8));
+ _mm_storel_epi64((__m128i*)&d4, x0);
+
+ /* (partial) h %= p */
+ d1 += sr(d0, 26); h0 = and(d0, 0x3ffffff);
+ d2 += sr(d1, 26); h1 = and(d1, 0x3ffffff);
+ d3 += sr(d2, 26); h2 = and(d2, 0x3ffffff);
+ d4 += sr(d3, 26); h3 = and(d3, 0x3ffffff);
+ h0 += sr(d4, 26) * 5; h4 = and(d4, 0x3ffffff);
+ h1 += h0 >> 26; h0 = h0 & 0x3ffffff;
+
+ this->h[0] = h0;
+ this->h[1] = h1;
+ this->h[2] = h2;
+ this->h[3] = h3;
+ this->h[4] = h4;
+}
+
+METHOD(chapoly_drv_t, poly, bool,
+ private_chapoly_drv_ssse3_t *this, u_char *data, u_int blocks)
+{
+ poly2(this, data, blocks / 2);
+ if (blocks-- % 2)
+ {
+ poly1(this, data + POLY_BLOCK_SIZE * blocks);
+ }
+ return TRUE;
+}
+
+METHOD(chapoly_drv_t, chacha, bool,
+ private_chapoly_drv_ssse3_t *this, u_char *stream)
+{
+ memset(stream, 0, CHACHA_BLOCK_SIZE);
+ chacha_block_xor(this, stream);
+
+ return TRUE;
+}
+
+METHOD(chapoly_drv_t, encrypt, bool,
+ private_chapoly_drv_ssse3_t *this, u_char *data, u_int blocks)
+{
+ while (blocks >= 4)
+ {
+ chacha_4block_xor(this, data);
+ poly2(this, data, 8);
+ data += CHACHA_BLOCK_SIZE * 4;
+ blocks -= 4;
+ }
+ while (blocks--)
+ {
+ chacha_block_xor(this, data);
+ poly2(this, data, 2);
+ data += CHACHA_BLOCK_SIZE;
+ }
+ return TRUE;
+}
+
+METHOD(chapoly_drv_t, decrypt, bool,
+ private_chapoly_drv_ssse3_t *this, u_char *data, u_int blocks)
+{
+ while (blocks >= 4)
+ {
+ poly2(this, data, 8);
+ chacha_4block_xor(this, data);
+ data += CHACHA_BLOCK_SIZE * 4;
+ blocks -= 4;
+ }
+ while (blocks--)
+ {
+ poly2(this, data, 2);
+ chacha_block_xor(this, data);
+ data += CHACHA_BLOCK_SIZE;
+ }
+ return TRUE;
+}
+
+METHOD(chapoly_drv_t, finish, bool,
+ private_chapoly_drv_ssse3_t *this, u_char *mac)
+{
+ u_int32_t h0, h1, h2, h3, h4;
+ u_int32_t g0, g1, g2, g3, g4;
+ u_int32_t mask;
+ u_int64_t f = 0;
+
+ /* fully carry h */
+ h0 = this->h[0];
+ h1 = this->h[1];
+ h2 = this->h[2];
+ h3 = this->h[3];
+ h4 = this->h[4];
+
+ h2 += (h1 >> 26); h1 = h1 & 0x3ffffff;
+ h3 += (h2 >> 26); h2 = h2 & 0x3ffffff;
+ h4 += (h3 >> 26); h3 = h3 & 0x3ffffff;
+ h0 += (h4 >> 26) * 5; h4 = h4 & 0x3ffffff;
+ h1 += (h0 >> 26); h0 = h0 & 0x3ffffff;
+
+ /* compute h + -p */
+ g0 = h0 + 5;
+ g1 = h1 + (g0 >> 26); g0 &= 0x3ffffff;
+ g2 = h2 + (g1 >> 26); g1 &= 0x3ffffff;
+ g3 = h3 + (g2 >> 26); g2 &= 0x3ffffff;
+ g4 = h4 + (g3 >> 26) - (1 << 26); g3 &= 0x3ffffff;
+
+ /* select h if h < p, or h + -p if h >= p */
+ mask = (g4 >> ((sizeof(u_int32_t) * 8) - 1)) - 1;
+ g0 &= mask;
+ g1 &= mask;
+ g2 &= mask;
+ g3 &= mask;
+ g4 &= mask;
+ mask = ~mask;
+ h0 = (h0 & mask) | g0;
+ h1 = (h1 & mask) | g1;
+ h2 = (h2 & mask) | g2;
+ h3 = (h3 & mask) | g3;
+ h4 = (h4 & mask) | g4;
+
+ /* h = h % (2^128) */
+ h0 = (h0 >> 0) | (h1 << 26);
+ h1 = (h1 >> 6) | (h2 << 20);
+ h2 = (h2 >> 12) | (h3 << 14);
+ h3 = (h3 >> 18) | (h4 << 8);
+
+ /* mac = (h + s) % (2^128) */
+ f = (f >> 32) + h0 + this->s[0]; wu32(mac + 0, f);
+ f = (f >> 32) + h1 + this->s[1]; wu32(mac + 4, f);
+ f = (f >> 32) + h2 + this->s[2]; wu32(mac + 8, f);
+ f = (f >> 32) + h3 + this->s[3]; wu32(mac + 12, f);
+
+ return TRUE;
+}
+
+METHOD(chapoly_drv_t, destroy, void,
+ private_chapoly_drv_ssse3_t *this)
+{
+ memwipe(this->m, sizeof(this->m));
+ memwipe(this->h, sizeof(this->h));
+ memwipe(this->r, sizeof(this->r));
+ memwipe(this->u, sizeof(this->u));
+ memwipe(this->s, sizeof(this->s));
+ free_align(this);
+}
+
+/**
+ * See header
+ */
+chapoly_drv_t *chapoly_drv_ssse3_create()
+{
+ private_chapoly_drv_ssse3_t *this;
+
+ if (!cpu_feature_available(CPU_FEATURE_SSSE3))
+ {
+ return FALSE;
+ }
+
+ INIT_ALIGN(this, sizeof(__m128i),
+ .public = {
+ .set_key = _set_key,
+ .init = _init,
+ .poly = _poly,
+ .chacha = _chacha,
+ .encrypt = _encrypt,
+ .decrypt = _decrypt,
+ .finish = _finish,
+ .destroy = _destroy,
+ },
+ );
+
+ return &this->public;
+}
+
+#else /* !__SSSE3__ */
+
+chapoly_drv_t *chapoly_drv_ssse3_create()
+{
+ return NULL;
+}
+
+#endif /* !__SSSE3__ */
diff --git a/src/libstrongswan/plugins/chapoly/chapoly_drv_ssse3.h b/src/libstrongswan/plugins/chapoly/chapoly_drv_ssse3.h
new file mode 100644
index 000000000..7e0e8084c
--- /dev/null
+++ b/src/libstrongswan/plugins/chapoly/chapoly_drv_ssse3.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup chapoly_drv_ssse3 chapoly_drv_ssse3
+ * @{ @ingroup chapoly
+ */
+
+#include "chapoly_drv.h"
+
+#ifndef CHAPOLY_DRV_SSSE3_H_
+#define CHAPOLY_DRV_SSSE3_H_
+
+/**
+ * Create a chapoly_drv_ssse3 instance.
+ */
+chapoly_drv_t *chapoly_drv_ssse3_create();
+
+#endif /** CHAPOLY_DRV_SSSE3_H_ @}*/
diff --git a/src/libstrongswan/plugins/chapoly/chapoly_plugin.c b/src/libstrongswan/plugins/chapoly/chapoly_plugin.c
new file mode 100644
index 000000000..02e7121d6
--- /dev/null
+++ b/src/libstrongswan/plugins/chapoly/chapoly_plugin.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "chapoly_plugin.h"
+#include "chapoly_aead.h"
+
+#include <library.h>
+
+typedef struct private_chapoly_plugin_t private_chapoly_plugin_t;
+
+/**
+ * Private data of chapoly_plugin
+ */
+struct private_chapoly_plugin_t {
+
+ /**
+ * Public functions
+ */
+ chapoly_plugin_t public;
+};
+
+METHOD(plugin_t, get_name, char*,
+ private_chapoly_plugin_t *this)
+{
+ return "chapoly";
+}
+
+METHOD(plugin_t, get_features, int,
+ private_chapoly_plugin_t *this, plugin_feature_t *features[])
+{
+ static plugin_feature_t f[] = {
+ PLUGIN_REGISTER(AEAD, chapoly_aead_create),
+ PLUGIN_PROVIDE(AEAD, ENCR_CHACHA20_POLY1305, 32),
+ };
+ *features = f;
+ return countof(f);
+}
+
+METHOD(plugin_t, destroy, void,
+ private_chapoly_plugin_t *this)
+{
+ free(this);
+}
+
+/*
+ * see header file
+ */
+plugin_t *chapoly_plugin_create()
+{
+ private_chapoly_plugin_t *this;
+
+ INIT(this,
+ .public = {
+ .plugin = {
+ .get_name = _get_name,
+ .get_features = _get_features,
+ .destroy = _destroy,
+ },
+ },
+ );
+
+ return &this->public.plugin;
+}
diff --git a/src/libstrongswan/plugins/chapoly/chapoly_plugin.h b/src/libstrongswan/plugins/chapoly/chapoly_plugin.h
new file mode 100644
index 000000000..f2b62e73c
--- /dev/null
+++ b/src/libstrongswan/plugins/chapoly/chapoly_plugin.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup chapoly chapoly
+ * @ingroup plugins
+ *
+ * @defgroup chapoly_plugin chapoly_plugin
+ * @{ @ingroup chapoly
+ */
+
+#ifndef CHAPOLY_PLUGIN_H_
+#define CHAPOLY_PLUGIN_H_
+
+#include <plugins/plugin.h>
+
+typedef struct chapoly_plugin_t chapoly_plugin_t;
+
+/**
+ * Plugin providing a ChaCha20/Poly1305 AEAD.
+ */
+struct chapoly_plugin_t {
+
+ /**
+ * Implements plugin interface.
+ */
+ plugin_t plugin;
+};
+
+#endif /** CHAPOLY_PLUGIN_H_ @}*/
diff --git a/src/libstrongswan/plugins/des/des_crypter.c b/src/libstrongswan/plugins/des/des_crypter.c
index c81318b19..6010f9d8b 100644
--- a/src/libstrongswan/plugins/des/des_crypter.c
+++ b/src/libstrongswan/plugins/des/des_crypter.c
@@ -112,7 +112,7 @@ struct private_des_crypter_t {
#endif
/* This helps C compiler generate the correct code for multiple functional
- * units. It reduces register dependancies at the expense of 2 more
+ * units. It reduces register dependencies at the expense of 2 more
* registers */
#ifndef DES_RISC1
#define DES_RISC1
diff --git a/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.h b/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.h
index 2d2b2b45d..bb45d7b4f 100644
--- a/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.h
+++ b/src/libstrongswan/plugins/padlock/padlock_sha1_hasher.h
@@ -15,7 +15,7 @@
*/
/**
- * @defgroup sha1_hasher sha1_hasher
+ * @defgroup padlock_sha1_hasher padlock_sha1_hasher
* @{ @ingroup padlock_p
*/
diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c
index 6d5211657..384777610 100644
--- a/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c
+++ b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c
@@ -439,12 +439,17 @@ static bool encode_rsa(private_pkcs11_public_key_t *this,
attr[0].ulValueLen > 0 && attr[1].ulValueLen > 0)
{
chunk_t n, e;
- n = chunk_create(attr[0].pValue, attr[0].ulValueLen);
+ /* some tokens/libraries add unnecessary 0x00 prefixes */
+ n = chunk_skip_zero(chunk_create(attr[0].pValue, attr[0].ulValueLen));
if (n.ptr[0] & 0x80)
- { /* add leading 0x00, encoders expect it already like this */
+ { /* add leading 0x00, encoders might expect it in two's complement */
n = chunk_cata("cc", chunk_from_chars(0x00), n);
}
- e = chunk_create(attr[1].pValue, attr[1].ulValueLen);
+ e = chunk_skip_zero(chunk_create(attr[1].pValue, attr[1].ulValueLen));
+ if (e.ptr[0] & 0x80)
+ {
+ e = chunk_cata("cc", chunk_from_chars(0x00), e);
+ }
success = lib->encoding->encode(lib->encoding, type, cache, encoding,
CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
}
diff --git a/src/libstrongswan/plugins/plugin_feature.c b/src/libstrongswan/plugins/plugin_feature.c
index 2d0ce8a4c..0ea5eeaf8 100644
--- a/src/libstrongswan/plugins/plugin_feature.c
+++ b/src/libstrongswan/plugins/plugin_feature.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 Tobias Brunner
+ * Copyright (C) 2012-2015 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2011 Martin Willi
@@ -59,7 +59,7 @@ ENUM(plugin_feature_names, FEATURE_NONE, FEATURE_CUSTOM,
*/
u_int32_t plugin_feature_hash(plugin_feature_t *feature)
{
- chunk_t data;
+ chunk_t data = chunk_empty;
switch (feature->type)
{
@@ -185,7 +185,8 @@ bool plugin_feature_matches(plugin_feature_t *a, plugin_feature_t *b)
return a->arg.container == b->arg.container;
case FEATURE_EAP_SERVER:
case FEATURE_EAP_PEER:
- return a->arg.eap == b->arg.eap;
+ return a->arg.eap.vendor == b->arg.eap.vendor &&
+ a->arg.eap.type == b->arg.eap.type;
case FEATURE_DATABASE:
return a->arg.database == DB_ANY ||
a->arg.database == b->arg.database;
@@ -368,8 +369,15 @@ char* plugin_feature_get_string(plugin_feature_t *feature)
break;
case FEATURE_EAP_SERVER:
case FEATURE_EAP_PEER:
- if (asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
- eap_type_short_names, feature->arg.eap) > 0)
+ if (feature->arg.eap.vendor &&
+ asprintf(&str, "%N:%d-%d", plugin_feature_names, feature->type,
+ feature->arg.eap.type, feature->arg.eap.vendor) > 0)
+ {
+ return str;
+ }
+ else if (!feature->arg.eap.vendor &&
+ asprintf(&str, "%N:%N", plugin_feature_names, feature->type,
+ eap_type_short_names, feature->arg.eap.type) > 0)
{
return str;
}
diff --git a/src/libstrongswan/plugins/plugin_feature.h b/src/libstrongswan/plugins/plugin_feature.h
index ea23f766c..03f1ba8cc 100644
--- a/src/libstrongswan/plugins/plugin_feature.h
+++ b/src/libstrongswan/plugins/plugin_feature.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 Tobias Brunner
+ * Copyright (C) 2012-2015 Tobias Brunner
* Hochschule fuer Technik Rapperswil
*
* Copyright (C) 2011 Martin Willi
@@ -196,7 +196,7 @@ struct plugin_feature_t {
/** FEATURE_CONTAINER_DECODE/ENCODE */
container_type_t container;
/** FEATURE_EAP_SERVER/CLIENT */
- eap_type_t eap;
+ eap_vendor_type_t eap;
/** FEATURE_DATABASE */
db_driver_t database;
/** FEATURE_FETCHER */
@@ -292,8 +292,10 @@ struct plugin_feature_t {
#define _PLUGIN_FEATURE_CERT_ENCODE(kind, type) __PLUGIN_FEATURE(kind, CERT_ENCODE, .cert = type)
#define _PLUGIN_FEATURE_CONTAINER_DECODE(kind, type) __PLUGIN_FEATURE(kind, CONTAINER_DECODE, .container = type)
#define _PLUGIN_FEATURE_CONTAINER_ENCODE(kind, type) __PLUGIN_FEATURE(kind, CONTAINER_ENCODE, .container = type)
-#define _PLUGIN_FEATURE_EAP_SERVER(kind, type) __PLUGIN_FEATURE(kind, EAP_SERVER, .eap = type)
-#define _PLUGIN_FEATURE_EAP_PEER(kind, type) __PLUGIN_FEATURE(kind, EAP_PEER, .eap = type)
+#define _PLUGIN_FEATURE_EAP_SERVER(kind, type) _PLUGIN_FEATURE_EAP_SERVER_VENDOR(kind, type, 0)
+#define _PLUGIN_FEATURE_EAP_PEER(kind, type) _PLUGIN_FEATURE_EAP_PEER_VENDOR(kind, type, 0)
+#define _PLUGIN_FEATURE_EAP_SERVER_VENDOR(kind, type, vendor)__PLUGIN_FEATURE(kind, EAP_SERVER, .eap = { type, vendor })
+#define _PLUGIN_FEATURE_EAP_PEER_VENDOR(kind, type, vendor) __PLUGIN_FEATURE(kind, EAP_PEER, .eap = { type, vendor })
#define _PLUGIN_FEATURE_DATABASE(kind, type) __PLUGIN_FEATURE(kind, DATABASE, .database = type)
#define _PLUGIN_FEATURE_FETCHER(kind, type) __PLUGIN_FEATURE(kind, FETCHER, .fetcher = type)
#define _PLUGIN_FEATURE_RESOLVER(kind, ...) __PLUGIN_FEATURE(kind, RESOLVER, .custom = NULL)
diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.am b/src/libstrongswan/plugins/test_vectors/Makefile.am
index bde27b873..72ba4ceef 100644
--- a/src/libstrongswan/plugins/test_vectors/Makefile.am
+++ b/src/libstrongswan/plugins/test_vectors/Makefile.am
@@ -19,6 +19,7 @@ libstrongswan_test_vectors_la_SOURCES = \
test_vectors/aes_cmac.c \
test_vectors/aes_ccm.c \
test_vectors/aes_gcm.c \
+ test_vectors/chacha20poly1305.c \
test_vectors/blowfish.c \
test_vectors/camellia_cbc.c \
test_vectors/camellia_ctr.c \
diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.in b/src/libstrongswan/plugins/test_vectors/Makefile.in
index e98119b85..fa7c3cb82 100644
--- a/src/libstrongswan/plugins/test_vectors/Makefile.in
+++ b/src/libstrongswan/plugins/test_vectors/Makefile.in
@@ -133,11 +133,11 @@ am_libstrongswan_test_vectors_la_OBJECTS = test_vectors_plugin.lo \
test_vectors/3des_cbc.lo test_vectors/aes_cbc.lo \
test_vectors/aes_ctr.lo test_vectors/aes_xcbc.lo \
test_vectors/aes_cmac.lo test_vectors/aes_ccm.lo \
- test_vectors/aes_gcm.lo test_vectors/blowfish.lo \
- test_vectors/camellia_cbc.lo test_vectors/camellia_ctr.lo \
- test_vectors/camellia_xcbc.lo test_vectors/cast.lo \
- test_vectors/des.lo test_vectors/idea.lo test_vectors/null.lo \
- test_vectors/rc2.lo test_vectors/rc5.lo \
+ test_vectors/aes_gcm.lo test_vectors/chacha20poly1305.lo \
+ test_vectors/blowfish.lo test_vectors/camellia_cbc.lo \
+ test_vectors/camellia_ctr.lo test_vectors/camellia_xcbc.lo \
+ test_vectors/cast.lo test_vectors/des.lo test_vectors/idea.lo \
+ test_vectors/null.lo test_vectors/rc2.lo test_vectors/rc5.lo \
test_vectors/serpent_cbc.lo test_vectors/twofish_cbc.lo \
test_vectors/md2.lo test_vectors/md4.lo test_vectors/md5.lo \
test_vectors/md5_hmac.lo test_vectors/sha1.lo \
@@ -461,6 +461,7 @@ libstrongswan_test_vectors_la_SOURCES = \
test_vectors/aes_cmac.c \
test_vectors/aes_ccm.c \
test_vectors/aes_gcm.c \
+ test_vectors/chacha20poly1305.c \
test_vectors/blowfish.c \
test_vectors/camellia_cbc.c \
test_vectors/camellia_ctr.c \
@@ -589,6 +590,8 @@ test_vectors/aes_ccm.lo: test_vectors/$(am__dirstamp) \
test_vectors/$(DEPDIR)/$(am__dirstamp)
test_vectors/aes_gcm.lo: test_vectors/$(am__dirstamp) \
test_vectors/$(DEPDIR)/$(am__dirstamp)
+test_vectors/chacha20poly1305.lo: test_vectors/$(am__dirstamp) \
+ test_vectors/$(DEPDIR)/$(am__dirstamp)
test_vectors/blowfish.lo: test_vectors/$(am__dirstamp) \
test_vectors/$(DEPDIR)/$(am__dirstamp)
test_vectors/camellia_cbc.lo: test_vectors/$(am__dirstamp) \
@@ -666,6 +669,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/camellia_ctr.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/camellia_xcbc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/cast.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/chacha20poly1305.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/des.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/ecp.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@test_vectors/$(DEPDIR)/ecpbp.Plo@am__quote@
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors.h b/src/libstrongswan/plugins/test_vectors/test_vectors.h
index f7450aa9e..57c218c16 100644
--- a/src/libstrongswan/plugins/test_vectors/test_vectors.h
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors.h
@@ -113,6 +113,10 @@ TEST_VECTOR_AEAD(aes_gcm21)
TEST_VECTOR_AEAD(aes_gcm22)
TEST_VECTOR_AEAD(aes_gcm23)
+TEST_VECTOR_AEAD(chacha20poly1305_1)
+TEST_VECTOR_AEAD(chacha20poly1305_2)
+TEST_VECTOR_AEAD(chacha20poly1305_3)
+
TEST_VECTOR_SIGNER(aes_xcbc_s1)
TEST_VECTOR_SIGNER(aes_xcbc_s2)
TEST_VECTOR_SIGNER(aes_xcbc_s3)
diff --git a/src/libstrongswan/plugins/test_vectors/test_vectors/chacha20poly1305.c b/src/libstrongswan/plugins/test_vectors/test_vectors/chacha20poly1305.c
new file mode 100644
index 000000000..21726cbbb
--- /dev/null
+++ b/src/libstrongswan/plugins/test_vectors/test_vectors/chacha20poly1305.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2015 Martin Willi
+ * Copyright (C) 2015 revosec AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the Licenseor (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 usefulbut
+ * 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 <crypto/crypto_tester.h>
+
+/**
+ * From draft-irtf-cfrg-chacha20-poly1305
+ */
+aead_test_vector_t chacha20poly1305_1 = {
+ .alg = ENCR_CHACHA20_POLY1305, .key_size = 32, .salt_size = 4,
+ .len = 265, .alen = 12,
+ .key = "\x1c\x92\x40\xa5\xeb\x55\xd3\x8a\xf3\x33\x88\x86\x04\xf6\xb5\xf0"
+ "\x47\x39\x17\xc1\x40\x2b\x80\x09\x9d\xca\x5c\xbc\x20\x70\x75\xc0"
+ "\x00\x00\x00\x00",
+ .iv = "\x01\x02\x03\x04\x05\x06\x07\x08",
+ .adata = "\xf3\x33\x88\x86\x00\x00\x00\x00\x00\x00\x4e\x91",
+ .plain = "\x49\x6e\x74\x65\x72\x6e\x65\x74\x2d\x44\x72\x61\x66\x74\x73\x20"
+ "\x61\x72\x65\x20\x64\x72\x61\x66\x74\x20\x64\x6f\x63\x75\x6d\x65"
+ "\x6e\x74\x73\x20\x76\x61\x6c\x69\x64\x20\x66\x6f\x72\x20\x61\x20"
+ "\x6d\x61\x78\x69\x6d\x75\x6d\x20\x6f\x66\x20\x73\x69\x78\x20\x6d"
+ "\x6f\x6e\x74\x68\x73\x20\x61\x6e\x64\x20\x6d\x61\x79\x20\x62\x65"
+ "\x20\x75\x70\x64\x61\x74\x65\x64\x2c\x20\x72\x65\x70\x6c\x61\x63"
+ "\x65\x64\x2c\x20\x6f\x72\x20\x6f\x62\x73\x6f\x6c\x65\x74\x65\x64"
+ "\x20\x62\x79\x20\x6f\x74\x68\x65\x72\x20\x64\x6f\x63\x75\x6d\x65"
+ "\x6e\x74\x73\x20\x61\x74\x20\x61\x6e\x79\x20\x74\x69\x6d\x65\x2e"
+ "\x20\x49\x74\x20\x69\x73\x20\x69\x6e\x61\x70\x70\x72\x6f\x70\x72"
+ "\x69\x61\x74\x65\x20\x74\x6f\x20\x75\x73\x65\x20\x49\x6e\x74\x65"
+ "\x72\x6e\x65\x74\x2d\x44\x72\x61\x66\x74\x73\x20\x61\x73\x20\x72"
+ "\x65\x66\x65\x72\x65\x6e\x63\x65\x20\x6d\x61\x74\x65\x72\x69\x61"
+ "\x6c\x20\x6f\x72\x20\x74\x6f\x20\x63\x69\x74\x65\x20\x74\x68\x65"
+ "\x6d\x20\x6f\x74\x68\x65\x72\x20\x74\x68\x61\x6e\x20\x61\x73\x20"
+ "\x2f\xe2\x80\x9c\x77\x6f\x72\x6b\x20\x69\x6e\x20\x70\x72\x6f\x67"
+ "\x72\x65\x73\x73\x2e\x2f\xe2\x80\x9d",
+ .cipher = "\x64\xa0\x86\x15\x75\x86\x1a\xf4\x60\xf0\x62\xc7\x9b\xe6\x43\xbd"
+ "\x5e\x80\x5c\xfd\x34\x5c\xf3\x89\xf1\x08\x67\x0a\xc7\x6c\x8c\xb2"
+ "\x4c\x6c\xfc\x18\x75\x5d\x43\xee\xa0\x9e\xe9\x4e\x38\x2d\x26\xb0"
+ "\xbd\xb7\xb7\x3c\x32\x1b\x01\x00\xd4\xf0\x3b\x7f\x35\x58\x94\xcf"
+ "\x33\x2f\x83\x0e\x71\x0b\x97\xce\x98\xc8\xa8\x4a\xbd\x0b\x94\x81"
+ "\x14\xad\x17\x6e\x00\x8d\x33\xbd\x60\xf9\x82\xb1\xff\x37\xc8\x55"
+ "\x97\x97\xa0\x6e\xf4\xf0\xef\x61\xc1\x86\x32\x4e\x2b\x35\x06\x38"
+ "\x36\x06\x90\x7b\x6a\x7c\x02\xb0\xf9\xf6\x15\x7b\x53\xc8\x67\xe4"
+ "\xb9\x16\x6c\x76\x7b\x80\x4d\x46\xa5\x9b\x52\x16\xcd\xe7\xa4\xe9"
+ "\x90\x40\xc5\xa4\x04\x33\x22\x5e\xe2\x82\xa1\xb0\xa0\x6c\x52\x3e"
+ "\xaf\x45\x34\xd7\xf8\x3f\xa1\x15\x5b\x00\x47\x71\x8c\xbc\x54\x6a"
+ "\x0d\x07\x2b\x04\xb3\x56\x4e\xea\x1b\x42\x22\x73\xf5\x48\x27\x1a"
+ "\x0b\xb2\x31\x60\x53\xfa\x76\x99\x19\x55\xeb\xd6\x31\x59\x43\x4e"
+ "\xce\xbb\x4e\x46\x6d\xae\x5a\x10\x73\xa6\x72\x76\x27\x09\x7a\x10"
+ "\x49\xe6\x17\xd9\x1d\x36\x10\x94\xfa\x68\xf0\xff\x77\x98\x71\x30"
+ "\x30\x5b\xea\xba\x2e\xda\x04\xdf\x99\x7b\x71\x4d\x6c\x6f\x2c\x29"
+ "\xa6\xad\x5c\xb4\x02\x2b\x02\x70\x9b\xee\xad\x9d\x67\x89\x0c\xbb"
+ "\x22\x39\x23\x36\xfe\xa1\x85\x1f\x38",
+};
+
+/**
+ * ESP example from draft-ietf-ipsecme-chacha20-poly1305-06
+ */
+aead_test_vector_t chacha20poly1305_2 = {
+ .alg = ENCR_CHACHA20_POLY1305, .key_size = 32, .salt_size = 4,
+ .len = 88, .alen = 8,
+ .key = "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+ "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+ "\xa0\xa1\xa2\xa3",
+ .iv = "\x10\x11\x12\x13\x14\x15\x16\x17",
+ .adata = "\x01\x02\x03\x04\x00\x00\x00\x05",
+ .plain = "\x45\x00\x00\x54\xa6\xf2\x00\x00\x40\x01\xe7\x78\xc6\x33\x64\x05"
+ "\xc0\x00\x02\x05\x08\x00\x5b\x7a\x3a\x08\x00\x00\x55\x3b\xec\x10"
+ "\x00\x07\x36\x27\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13"
+ "\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23"
+ "\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33"
+ "\x34\x35\x36\x37\x01\x02\x02\x04",
+ .cipher = "\x24\x03\x94\x28\xb9\x7f\x41\x7e\x3c\x13\x75\x3a\x4f\x05\x08\x7b"
+ "\x67\xc3\x52\xe6\xa7\xfa\xb1\xb9\x82\xd4\x66\xef\x40\x7a\xe5\xc6"
+ "\x14\xee\x80\x99\xd5\x28\x44\xeb\x61\xaa\x95\xdf\xab\x4c\x02\xf7"
+ "\x2a\xa7\x1e\x7c\x4c\x4f\x64\xc9\xbe\xfe\x2f\xac\xc6\x38\xe8\xf3"
+ "\xcb\xec\x16\x3f\xac\x46\x9b\x50\x27\x73\xf6\xfb\x94\xe6\x64\xda"
+ "\x91\x65\xb8\x28\x29\xf6\x41\xe0\x76\xaa\xa8\x26\x6b\x7f\xb0\xf7"
+ "\xb1\x1b\x36\x99\x07\xe1\xad\x43",
+};
+
+/**
+ * IKEv2 example from draft-ietf-ipsecme-chacha20-poly1305-06
+ */
+aead_test_vector_t chacha20poly1305_3 = {
+ .alg = ENCR_CHACHA20_POLY1305, .key_size = 32, .salt_size = 4,
+ .len = 13, .alen = 32,
+ .key = "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f"
+ "\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f"
+ "\xa0\xa1\xa2\xa3",
+ .iv = "\x10\x11\x12\x13\x14\x15\x16\x17",
+ .adata = "\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7"
+ "\x2e\x20\x25\x00\x00\x00\x00\x09\x00\x00\x00\x45\x29\x00\x00\x29",
+ .plain = "\x00\x00\x00\x0c\x00\x00\x40\x01\x00\x00\x00\x0a\x00",
+ .cipher = "\x61\x03\x94\x70\x1f\x8d\x01\x7f\x7c\x12\x92\x48\x89\x6b\x71\xbf"
+ "\xe2\x52\x36\xef\xd7\xcd\xc6\x70\x66\x90\x63\x15\xb2",
+};
diff --git a/src/libstrongswan/selectors/traffic_selector.c b/src/libstrongswan/selectors/traffic_selector.c
index 3b7f8c5a0..668632459 100644
--- a/src/libstrongswan/selectors/traffic_selector.c
+++ b/src/libstrongswan/selectors/traffic_selector.c
@@ -849,8 +849,7 @@ traffic_selector_t *traffic_selector_create_from_rfc3779_format(ts_type_t type,
memcpy(this->to, to.ptr+1, to.len-1);
this->to[to.len-2] |= mask;
}
- this->netbits = chunk_equals(from, to) ? (from.len-1)*8 - from.ptr[0]
- : NON_SUBNET_ADDRESS_RANGE;
+ calc_netbits(this);
return (&this->public);
}
diff --git a/src/libstrongswan/settings/settings.c b/src/libstrongswan/settings/settings.c
index acf9160d2..305ebe620 100644
--- a/src/libstrongswan/settings/settings.c
+++ b/src/libstrongswan/settings/settings.c
@@ -37,9 +37,10 @@
typedef struct private_settings_t private_settings_t;
/**
- * Parse function provided by the generated parser.
+ * Parse functions provided by the generated parser.
*/
bool settings_parser_parse_file(section_t *root, char *name);
+bool settings_parser_parse_string(section_t *root, char *settings);
/**
* Private data of settings
@@ -843,16 +844,17 @@ METHOD(settings_t, add_fallback, void,
}
/**
- * Load settings from files matching the given file pattern.
+ * Load settings from files matching the given file pattern or from a string.
* All sections and values are added relative to "parent".
* All files (even included ones) have to be loaded successfully.
* If merge is FALSE the contents of parent are replaced with the parsed
* contents, otherwise they are merged together.
*/
-static bool load_files_internal(private_settings_t *this, section_t *parent,
- char *pattern, bool merge)
+static bool load_internal(private_settings_t *this, section_t *parent,
+ char *pattern, bool merge, bool string)
{
section_t *section;
+ bool loaded;
if (pattern == NULL || !pattern[0])
{ /* TODO: Clear parent if merge is FALSE? */
@@ -860,7 +862,9 @@ static bool load_files_internal(private_settings_t *this, section_t *parent,
}
section = settings_section_create(NULL);
- if (!settings_parser_parse_file(section, pattern))
+ loaded = string ? settings_parser_parse_string(section, pattern) :
+ settings_parser_parse_file(section, pattern);
+ if (!loaded)
{
settings_section_destroy(section, NULL);
return FALSE;
@@ -877,7 +881,7 @@ static bool load_files_internal(private_settings_t *this, section_t *parent,
METHOD(settings_t, load_files, bool,
private_settings_t *this, char *pattern, bool merge)
{
- return load_files_internal(this, this->top, pattern, merge);
+ return load_internal(this, this->top, pattern, merge, FALSE);
}
METHOD(settings_t, load_files_section, bool,
@@ -894,7 +898,30 @@ METHOD(settings_t, load_files_section, bool,
{
return FALSE;
}
- return load_files_internal(this, section, pattern, merge);
+ return load_internal(this, section, pattern, merge, FALSE);
+}
+
+METHOD(settings_t, load_string, bool,
+ private_settings_t *this, char *settings, bool merge)
+{
+ return load_internal(this, this->top, settings, merge, TRUE);
+}
+
+METHOD(settings_t, load_string_section, bool,
+ private_settings_t *this, char *settings, bool merge, char *key, ...)
+{
+ section_t *section;
+ va_list args;
+
+ va_start(args, key);
+ section = ensure_section(this, this->top, key, args);
+ va_end(args);
+
+ if (!section)
+ {
+ return FALSE;
+ }
+ return load_internal(this, section, settings, merge, TRUE);
}
METHOD(settings_t, destroy, void,
@@ -906,10 +933,7 @@ METHOD(settings_t, destroy, void,
free(this);
}
-/*
- * see header file
- */
-settings_t *settings_create(char *file)
+static private_settings_t *settings_create_base()
{
private_settings_t *this;
@@ -931,14 +955,37 @@ settings_t *settings_create(char *file)
.add_fallback = _add_fallback,
.load_files = _load_files,
.load_files_section = _load_files_section,
+ .load_string = _load_string,
+ .load_string_section = _load_string_section,
.destroy = _destroy,
},
.top = settings_section_create(NULL),
.contents = array_create(0, 0),
.lock = rwlock_create(RWLOCK_TYPE_DEFAULT),
);
+ return this;
+}
+
+/*
+ * see header file
+ */
+settings_t *settings_create(char *file)
+{
+ private_settings_t *this = settings_create_base();
load_files(this, file, FALSE);
return &this->public;
}
+
+/*
+ * see header file
+ */
+settings_t *settings_create_string(char *settings)
+{
+ private_settings_t *this = settings_create_base();
+
+ load_string(this, settings, FALSE);
+
+ return &this->public;
+}
diff --git a/src/libstrongswan/settings/settings.h b/src/libstrongswan/settings/settings.h
index 3b87c8feb..4ef80d0f6 100644
--- a/src/libstrongswan/settings/settings.h
+++ b/src/libstrongswan/settings/settings.h
@@ -335,6 +335,50 @@ struct settings_t {
char *section, ...);
/**
+ * Load settings from the given string.
+ *
+ * If merge is TRUE, existing sections are extended, existing values
+ * replaced, by those found in the string. If it is FALSE, existing
+ * sections are purged before reading the new config.
+ *
+ * @note If the string contains _include_ statements they should be
+ * absolute paths.
+ *
+ * @note If any failures occur, no settings are added at all. So, it's all
+ * or nothing.
+ *
+ * @param settings string to parse
+ * @param merge TRUE to merge config with existing values
+ * @return TRUE, if settings were loaded successfully
+ */
+ bool (*load_string)(settings_t *this, char *settings, bool merge);
+
+ /**
+ * Load settings from the given string.
+ *
+ * If merge is TRUE, existing sections are extended, existing values
+ * replaced, by those found in the string. If it is FALSE, existing
+ * sections are purged before reading the new config.
+ *
+ * All settings are loaded relative to the given section. The section is
+ * created, if it does not yet exist.
+ *
+ * @note If the string contains _include_ statements they should be
+ * absolute paths.
+ *
+ * @note If any failures occur, no settings are added at all. So, it's all
+ * or nothing.
+ *
+ * @param settings string to parse
+ * @param merge TRUE to merge config with existing values
+ * @param section section name of parent section, printf style
+ * @param ... argument list for section
+ * @return TRUE, if settings were loaded successfully
+ */
+ bool (*load_string_section)(settings_t *this, char *settings, bool merge,
+ char *section, ...);
+
+ /**
* Destroy a settings instance.
*/
void (*destroy)(settings_t *this);
@@ -350,4 +394,14 @@ struct settings_t {
*/
settings_t *settings_create(char *file);
+/**
+ * Load settings from a string.
+ *
+ * @note If parsing the file fails the object is still created.
+ *
+ * @param settings string to read settings from
+ * @return settings object, or NULL
+ */
+settings_t *settings_create_string(char *settings);
+
#endif /** SETTINGS_H_ @}*/
diff --git a/src/libstrongswan/settings/settings_lexer.c b/src/libstrongswan/settings/settings_lexer.c
index 0d71a1d01..6e64e15a6 100644
--- a/src/libstrongswan/settings/settings_lexer.c
+++ b/src/libstrongswan/settings/settings_lexer.c
@@ -456,8 +456,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
yyg->yy_c_buf_p = yy_cp;
/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
-#define YY_NUM_RULES 26
-#define YY_END_OF_BUFFER 27
+#define YY_NUM_RULES 23
+#define YY_END_OF_BUFFER 24
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -465,14 +465,13 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[52] =
+static yyconst flex_int16_t yy_accept[49] =
{ 0,
- 0, 0, 0, 0, 0, 0, 27, 9, 2, 3,
+ 0, 0, 0, 0, 0, 0, 24, 9, 2, 3,
8, 1, 6, 9, 4, 5, 14, 10, 11, 12,
- 25, 16, 15, 17, 9, 2, 1, 1, 3, 9,
- 14, 13, 25, 24, 23, 24, 21, 22, 18, 19,
- 20, 1, 9, 9, 9, 9, 9, 0, 7, 7,
- 0
+ 22, 15, 16, 9, 2, 1, 1, 3, 9, 14,
+ 13, 22, 21, 20, 21, 17, 18, 19, 1, 9,
+ 9, 9, 9, 9, 0, 7, 7, 0
} ;
static yyconst flex_int32_t yy_ec[256] =
@@ -486,11 +485,11 @@ static yyconst flex_int32_t yy_ec[256] =
8, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 9, 1, 1, 1, 1, 1, 10, 11, 12,
+ 1, 9, 1, 1, 1, 1, 1, 1, 10, 11,
- 13, 14, 1, 1, 15, 1, 1, 16, 1, 17,
- 1, 1, 1, 18, 1, 19, 20, 1, 1, 1,
- 1, 1, 21, 1, 22, 1, 1, 1, 1, 1,
+ 12, 1, 1, 1, 13, 1, 1, 14, 1, 15,
+ 1, 1, 1, 16, 1, 17, 18, 1, 1, 1,
+ 1, 1, 19, 1, 20, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -507,92 +506,91 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst flex_int32_t yy_meta[23] =
+static yyconst flex_int32_t yy_meta[21] =
{ 0,
1, 2, 3, 1, 4, 5, 4, 6, 7, 1,
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 8, 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 8, 9
} ;
-static yyconst flex_int16_t yy_base[62] =
+static yyconst flex_int16_t yy_base[60] =
{ 0,
- 0, 0, 21, 42, 26, 28, 63, 0, 31, 155,
- 155, 59, 155, 44, 155, 155, 0, 155, 155, 0,
- 0, 155, 155, 62, 0, 48, 0, 57, 155, 47,
- 0, 155, 0, 155, 155, 49, 155, 155, 155, 155,
- 155, 0, 30, 21, 28, 12, 37, 52, 155, 54,
- 155, 81, 89, 97, 104, 112, 117, 122, 130, 138,
- 146
+ 0, 0, 19, 38, 21, 23, 55, 0, 47, 161,
+ 161, 50, 161, 37, 161, 161, 0, 161, 161, 0,
+ 0, 161, 56, 0, 44, 0, 47, 161, 39, 0,
+ 161, 0, 161, 161, 45, 161, 161, 161, 0, 32,
+ 24, 26, 11, 29, 31, 161, 33, 161, 73, 82,
+ 91, 97, 101, 110, 115, 124, 133, 142, 151
} ;
-static yyconst flex_int16_t yy_def[62] =
+static yyconst flex_int16_t yy_def[60] =
{ 0,
- 51, 1, 52, 52, 53, 53, 51, 54, 51, 51,
- 51, 55, 51, 54, 51, 51, 56, 51, 51, 57,
- 58, 51, 51, 59, 54, 51, 60, 55, 51, 54,
- 56, 51, 58, 51, 51, 51, 51, 51, 51, 51,
- 51, 60, 54, 54, 54, 54, 54, 61, 51, 61,
- 0, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51
+ 48, 1, 49, 49, 50, 50, 48, 51, 52, 48,
+ 48, 53, 48, 51, 48, 48, 54, 48, 48, 55,
+ 56, 48, 57, 51, 52, 58, 53, 48, 51, 54,
+ 48, 56, 48, 48, 48, 48, 48, 48, 58, 51,
+ 51, 51, 51, 51, 59, 48, 59, 0, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48
} ;
-static yyconst flex_int16_t yy_nxt[178] =
+static yyconst flex_int16_t yy_nxt[182] =
{ 0,
8, 9, 10, 8, 9, 11, 12, 13, 8, 8,
- 8, 8, 8, 8, 14, 8, 8, 8, 8, 8,
- 15, 16, 18, 18, 47, 18, 19, 18, 22, 20,
- 22, 23, 26, 23, 24, 26, 24, 27, 48, 46,
- 45, 48, 18, 18, 18, 44, 18, 19, 18, 26,
- 20, 35, 26, 50, 27, 50, 50, 43, 50, 29,
- 30, 29, 51, 18, 35, 36, 51, 51, 51, 51,
- 51, 37, 51, 51, 51, 38, 51, 51, 39, 40,
- 41, 17, 17, 17, 17, 17, 17, 17, 17, 21,
- 21, 21, 21, 21, 21, 21, 21, 25, 51, 51,
-
- 51, 51, 51, 25, 28, 28, 28, 28, 28, 28,
- 28, 28, 31, 51, 51, 51, 51, 31, 51, 31,
- 32, 32, 33, 33, 51, 33, 51, 33, 51, 33,
- 34, 34, 34, 34, 34, 34, 34, 34, 42, 42,
- 51, 42, 42, 42, 42, 42, 49, 49, 49, 49,
- 49, 51, 49, 49, 7, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51
+ 8, 8, 14, 8, 8, 8, 8, 8, 15, 16,
+ 18, 18, 44, 18, 19, 18, 22, 20, 22, 23,
+ 45, 23, 47, 45, 47, 47, 43, 47, 18, 18,
+ 18, 42, 18, 19, 18, 41, 20, 34, 40, 28,
+ 26, 29, 28, 26, 48, 48, 48, 18, 34, 35,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 36, 37, 38, 17, 17, 17, 17, 17, 17, 17,
+ 17, 17, 21, 21, 21, 21, 21, 21, 21, 21,
+ 21, 24, 48, 48, 48, 48, 48, 24, 25, 48,
+
+ 25, 27, 27, 27, 27, 27, 27, 27, 27, 27,
+ 30, 48, 48, 48, 48, 30, 48, 30, 31, 31,
+ 48, 48, 48, 31, 32, 32, 32, 32, 48, 32,
+ 48, 32, 32, 33, 33, 33, 33, 33, 33, 33,
+ 33, 33, 39, 39, 48, 39, 39, 39, 39, 39,
+ 39, 46, 46, 46, 46, 46, 48, 46, 46, 46,
+ 7, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48
} ;
-static yyconst flex_int16_t yy_chk[178] =
+static yyconst flex_int16_t yy_chk[182] =
{ 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 3, 3, 46, 3, 3, 3, 5, 3,
- 6, 5, 9, 6, 5, 9, 6, 9, 47, 45,
- 44, 47, 3, 4, 4, 43, 4, 4, 4, 26,
- 4, 36, 26, 48, 26, 50, 48, 30, 50, 28,
- 14, 12, 7, 4, 24, 24, 0, 0, 0, 0,
- 0, 24, 0, 0, 0, 24, 0, 0, 24, 24,
- 24, 52, 52, 52, 52, 52, 52, 52, 52, 53,
- 53, 53, 53, 53, 53, 53, 53, 54, 0, 0,
-
- 0, 0, 0, 54, 55, 55, 55, 55, 55, 55,
- 55, 55, 56, 0, 0, 0, 0, 56, 0, 56,
- 57, 57, 58, 58, 0, 58, 0, 58, 0, 58,
- 59, 59, 59, 59, 59, 59, 59, 59, 60, 60,
- 0, 60, 60, 60, 60, 60, 61, 61, 61, 61,
- 61, 0, 61, 61, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51, 51, 51, 51,
- 51, 51, 51, 51, 51, 51, 51
+ 3, 3, 43, 3, 3, 3, 5, 3, 6, 5,
+ 44, 6, 45, 44, 47, 45, 42, 47, 3, 4,
+ 4, 41, 4, 4, 4, 40, 4, 35, 29, 27,
+ 25, 14, 12, 9, 7, 0, 0, 4, 23, 23,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 23, 23, 23, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 50, 50, 50, 50, 50, 50, 50, 50,
+ 50, 51, 0, 0, 0, 0, 0, 51, 52, 0,
+
+ 52, 53, 53, 53, 53, 53, 53, 53, 53, 53,
+ 54, 0, 0, 0, 0, 54, 0, 54, 55, 55,
+ 0, 0, 0, 55, 56, 56, 56, 56, 0, 56,
+ 0, 56, 56, 57, 57, 57, 57, 57, 57, 57,
+ 57, 57, 58, 58, 0, 58, 58, 58, 58, 58,
+ 58, 59, 59, 59, 59, 59, 0, 59, 59, 59,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48
} ;
/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[27] =
+static yyconst flex_int32_t yy_rule_can_match_eol[24] =
{ 0,
-0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0,
- 0, 0, 0, 1, 0, 0, 0, };
+0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 0, 1, 0, };
-static yyconst flex_int16_t yy_rule_linenum[26] =
+static yyconst flex_int16_t yy_rule_linenum[23] =
{ 0,
59, 60, 61, 63, 64, 65, 67, 72, 77, 85,
- 105, 108, 111, 114, 120, 122, 123, 146, 147, 148,
- 149, 150, 151, 152, 153
+ 105, 108, 111, 114, 120, 122, 141, 142, 143, 144,
+ 145, 146
} ;
/* The intent behind this definition is that it'll catch
@@ -640,7 +638,7 @@ static void include_files(parser_helper_t *ctx);
/* state used to scan quoted strings */
-#line 644 "settings/settings_lexer.c"
+#line 642 "settings/settings_lexer.c"
#define INITIAL 0
#define inc 1
@@ -952,7 +950,7 @@ YY_DECL
#line 57 "settings/settings_lexer.l"
-#line 956 "settings/settings_lexer.c"
+#line 954 "settings/settings_lexer.c"
yylval = yylval_param;
@@ -1017,13 +1015,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 52 )
+ if ( yy_current_state >= 49 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 155 );
+ while ( yy_base[yy_current_state] != 161 );
yy_find_action:
/* %% [10.0] code to find the action number goes here */
@@ -1058,13 +1056,13 @@ do_action: /* This label is used only to access EOF actions. */
{
if ( yy_act == 0 )
fprintf( stderr, "--scanner backing up\n" );
- else if ( yy_act < 26 )
+ else if ( yy_act < 23 )
fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
(long)yy_rule_linenum[yy_act], yytext );
- else if ( yy_act == 26 )
+ else if ( yy_act == 23 )
fprintf( stderr, "--accepting default rule (\"%s\")\n",
yytext );
- else if ( yy_act == 27 )
+ else if ( yy_act == 24 )
fprintf( stderr, "--(end of buffer or a NUL)\n" );
else
fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@ -1197,21 +1195,13 @@ case 15:
case YY_STATE_EOF(str):
#line 121 "settings/settings_lexer.l"
case 16:
-/* rule 16 can match eol */
-#line 123 "settings/settings_lexer.l"
-case 17:
-/* rule 17 can match eol */
YY_RULE_SETUP
-#line 123 "settings/settings_lexer.l"
+#line 122 "settings/settings_lexer.l"
{
if (!streq(yytext, "\""))
{
- if (streq(yytext, "\n"))
- { /* put the newline back to fix the line numbers */
- unput('\n');
- yy_set_bol(0);
- }
PARSER_DBG1(yyextra, "unterminated string detected");
+ return STRING_ERROR;
}
if (yy_top_state(yyscanner) == inc)
{ /* string include */
@@ -1227,52 +1217,43 @@ YY_RULE_SETUP
}
}
YY_BREAK
-case 18:
+case 17:
YY_RULE_SETUP
-#line 146 "settings/settings_lexer.l"
+#line 141 "settings/settings_lexer.l"
yyextra->string_add(yyextra, "\n");
YY_BREAK
-case 19:
+case 18:
YY_RULE_SETUP
-#line 147 "settings/settings_lexer.l"
+#line 142 "settings/settings_lexer.l"
yyextra->string_add(yyextra, "\r");
YY_BREAK
-case 20:
+case 19:
YY_RULE_SETUP
-#line 148 "settings/settings_lexer.l"
+#line 143 "settings/settings_lexer.l"
yyextra->string_add(yyextra, "\t");
YY_BREAK
-case 21:
-YY_RULE_SETUP
-#line 149 "settings/settings_lexer.l"
-yyextra->string_add(yyextra, "\b");
- YY_BREAK
-case 22:
-YY_RULE_SETUP
-#line 150 "settings/settings_lexer.l"
-yyextra->string_add(yyextra, "\f");
- YY_BREAK
-case 23:
-/* rule 23 can match eol */
+case 20:
+/* rule 20 can match eol */
YY_RULE_SETUP
-#line 151 "settings/settings_lexer.l"
+#line 144 "settings/settings_lexer.l"
/* merge lines that end with EOL characters */
YY_BREAK
-case 24:
+case 21:
YY_RULE_SETUP
-#line 152 "settings/settings_lexer.l"
+#line 145 "settings/settings_lexer.l"
yyextra->string_add(yyextra, yytext+1);
YY_BREAK
-case 25:
+case 22:
+/* rule 22 can match eol */
YY_RULE_SETUP
-#line 153 "settings/settings_lexer.l"
+#line 146 "settings/settings_lexer.l"
{
yyextra->string_add(yyextra, yytext);
}
YY_BREAK
case YY_STATE_EOF(INITIAL):
-#line 158 "settings/settings_lexer.l"
+#line 151 "settings/settings_lexer.l"
{
settings_parser_pop_buffer_state(yyscanner);
if (!settings_parser_open_next_file(yyextra) && !YY_CURRENT_BUFFER)
@@ -1281,12 +1262,12 @@ case YY_STATE_EOF(INITIAL):
}
}
YY_BREAK
-case 26:
+case 23:
YY_RULE_SETUP
-#line 166 "settings/settings_lexer.l"
+#line 159 "settings/settings_lexer.l"
YY_FATAL_ERROR( "flex scanner jammed" );
YY_BREAK
-#line 1290 "settings/settings_lexer.c"
+#line 1271 "settings/settings_lexer.c"
case YY_END_OF_BUFFER:
{
@@ -1599,7 +1580,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 52 )
+ if ( yy_current_state >= 49 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1633,11 +1614,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 52 )
+ if ( yy_current_state >= 49 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 51);
+ yy_is_jam = (yy_current_state == 48);
return yy_is_jam ? 0 : yy_current_state;
}
@@ -2654,7 +2635,7 @@ void settings_parser_free (void * ptr , yyscan_t yyscanner)
/* %ok-for-header */
-#line 166 "settings/settings_lexer.l"
+#line 159 "settings/settings_lexer.l"
@@ -2692,3 +2673,11 @@ static void include_files(parser_helper_t *ctx)
settings_parser_open_next_file(ctx);
}
+/**
+ * Load the given string to be parsed next
+ */
+void settings_parser_load_string(parser_helper_t *ctx, const char *content)
+{
+ settings_parser__scan_string(content, ctx->scanner);
+}
+
diff --git a/src/libstrongswan/settings/settings_lexer.l b/src/libstrongswan/settings/settings_lexer.l
index 176387f1f..ce9d4eedc 100644
--- a/src/libstrongswan/settings/settings_lexer.l
+++ b/src/libstrongswan/settings/settings_lexer.l
@@ -119,16 +119,11 @@ static void include_files(parser_helper_t *ctx);
<str>{
"\"" |
<<EOF>> |
- \n |
\\ {
if (!streq(yytext, "\""))
{
- if (streq(yytext, "\n"))
- { /* put the newline back to fix the line numbers */
- unput('\n');
- yy_set_bol(0);
- }
PARSER_DBG1(yyextra, "unterminated string detected");
+ return STRING_ERROR;
}
if (yy_top_state(yyscanner) == inc)
{ /* string include */
@@ -146,11 +141,9 @@ static void include_files(parser_helper_t *ctx);
\\n yyextra->string_add(yyextra, "\n");
\\r yyextra->string_add(yyextra, "\r");
\\t yyextra->string_add(yyextra, "\t");
- \\b yyextra->string_add(yyextra, "\b");
- \\f yyextra->string_add(yyextra, "\f");
\\\r?\n /* merge lines that end with EOL characters */
\\. yyextra->string_add(yyextra, yytext+1);
- [^\\\n"]+ {
+ [^\\"]+ {
yyextra->string_add(yyextra, yytext);
}
}
@@ -198,3 +191,11 @@ static void include_files(parser_helper_t *ctx)
settings_parser_open_next_file(ctx);
}
+
+/**
+ * Load the given string to be parsed next
+ */
+void settings_parser_load_string(parser_helper_t *ctx, const char *content)
+{
+ settings_parser__scan_string(content, ctx->scanner);
+}
diff --git a/src/libstrongswan/settings/settings_parser.c b/src/libstrongswan/settings/settings_parser.c
index be805efc9..6cd3b177a 100644
--- a/src/libstrongswan/settings/settings_parser.c
+++ b/src/libstrongswan/settings/settings_parser.c
@@ -110,6 +110,7 @@ int settings_parser_get_leng(void *scanner);
int settings_parser_get_lineno(void *scanner);
/* Custom functions in lexer */
bool settings_parser_open_next_file(parser_helper_t *ctx);
+bool settings_parser_load_string(parser_helper_t *ctx, const char *content);
/**
* Forward declarations
@@ -130,7 +131,7 @@ static int yylex(YYSTYPE *lvalp, parser_helper_t *ctx)
}
-#line 134 "settings/settings_parser.c" /* yacc.c:339 */
+#line 135 "settings/settings_parser.c" /* yacc.c:339 */
# ifndef YY_NULLPTR
# if defined __cplusplus && 201103L <= __cplusplus
@@ -167,26 +168,28 @@ extern int settings_parser_debug;
{
NAME = 258,
STRING = 259,
- NEWLINE = 260
+ NEWLINE = 260,
+ STRING_ERROR = 261
};
#endif
/* Tokens. */
#define NAME 258
#define STRING 259
#define NEWLINE 260
+#define STRING_ERROR 261
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE YYSTYPE;
union YYSTYPE
{
-#line 76 "settings/settings_parser.y" /* yacc.c:355 */
+#line 77 "settings/settings_parser.y" /* yacc.c:355 */
char *s;
struct section_t *sec;
struct kv_t *kv;
-#line 190 "settings/settings_parser.c" /* yacc.c:355 */
+#line 193 "settings/settings_parser.c" /* yacc.c:355 */
};
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
@@ -200,7 +203,7 @@ int settings_parser_parse (parser_helper_t *ctx);
/* Copy the second part of user declarations. */
-#line 204 "settings/settings_parser.c" /* yacc.c:358 */
+#line 207 "settings/settings_parser.c" /* yacc.c:358 */
#ifdef short
# undef short
@@ -445,7 +448,7 @@ union yyalloc
#define YYLAST 13
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 9
+#define YYNTOKENS 10
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 8
/* YYNRULES -- Number of rules. */
@@ -456,7 +459,7 @@ union yyalloc
/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 260
+#define YYMAXUTOK 261
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -471,13 +474,13 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 8, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 9, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
- 2, 2, 2, 7, 2, 6, 2, 2, 2, 2,
+ 2, 2, 2, 8, 2, 7, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
@@ -491,15 +494,15 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
- 5
+ 5, 6
};
#if YYDEBUG
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 104, 104, 106, 107, 111, 115, 122, 130, 135,
- 142, 147, 154, 155, 169, 170
+ 0, 105, 105, 107, 108, 112, 116, 123, 131, 136,
+ 143, 148, 155, 156, 170, 171
};
#endif
@@ -508,9 +511,9 @@ static const yytype_uint8 yyrline[] =
First, the terminals, then, starting at YYNTOKENS, nonterminals. */
static const char *const yytname[] =
{
- "$end", "error", "$undefined", "NAME", "STRING", "NEWLINE", "'}'",
- "'{'", "'='", "$accept", "statements", "statement", "section",
- "section_start", "setting", "value", "valuepart", YY_NULLPTR
+ "$end", "error", "$undefined", "NAME", "STRING", "NEWLINE",
+ "STRING_ERROR", "'}'", "'{'", "'='", "$accept", "statements",
+ "statement", "section", "section_start", "setting", "value", "valuepart", YY_NULLPTR
};
#endif
@@ -519,14 +522,14 @@ static const char *const yytname[] =
(internal) symbol number NUM (which must be that of a token). */
static const yytype_uint16 yytoknum[] =
{
- 0, 256, 257, 258, 259, 260, 125, 123, 61
+ 0, 256, 257, 258, 259, 260, 261, 125, 123, 61
};
# endif
-#define YYPACT_NINF -5
+#define YYPACT_NINF -11
#define yypact_value_is_default(Yystate) \
- (!!((Yystate) == (-5)))
+ (!!((Yystate) == (-11)))
#define YYTABLE_NINF -1
@@ -537,8 +540,8 @@ static const yytype_uint16 yytoknum[] =
STATE-NUM. */
static const yytype_int8 yypact[] =
{
- -5, 0, -5, -1, -5, -5, -5, -5, -5, 2,
- -5, -2, 5, -5, -5, -5, -2, -5, -5, -5
+ -11, 0, -11, -1, -11, -11, -11, -11, -11, 2,
+ -11, -2, 6, -11, -11, -11, -2, -11, -11, -11
};
/* YYDEFACT[STATE-NUM] -- Default reduction number in state STATE-NUM.
@@ -553,7 +556,7 @@ static const yytype_uint8 yydefact[] =
/* YYPGOTO[NTERM-NUM]. */
static const yytype_int8 yypgoto[] =
{
- -5, 6, -5, -5, -5, -5, -5, -4
+ -11, 5, -11, -11, -11, -11, -11, -10
};
/* YYDEFGOTO[NTERM-NUM]. */
@@ -567,29 +570,29 @@ static const yytype_int8 yydefgoto[] =
number is the opposite. If YYTABLE_NINF, syntax error. */
static const yytype_uint8 yytable[] =
{
- 2, 14, 15, 3, 9, 4, 10, 11, 3, 13,
- 4, 18, 19, 12
+ 2, 14, 15, 3, 9, 4, 19, 10, 11, 3,
+ 13, 4, 12, 18
};
static const yytype_uint8 yycheck[] =
{
- 0, 3, 4, 3, 5, 5, 7, 8, 3, 7,
- 5, 6, 16, 7
+ 0, 3, 4, 3, 5, 5, 16, 8, 9, 3,
+ 8, 5, 7, 7
};
/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 10, 0, 3, 5, 11, 12, 13, 14, 5,
- 7, 8, 10, 7, 3, 4, 15, 16, 6, 16
+ 0, 11, 0, 3, 5, 12, 13, 14, 15, 5,
+ 8, 9, 11, 8, 3, 4, 16, 17, 7, 17
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 9, 10, 10, 10, 11, 11, 12, 13, 13,
- 14, 14, 15, 15, 16, 16
+ 0, 10, 11, 11, 11, 12, 12, 13, 14, 14,
+ 15, 15, 16, 16, 17, 17
};
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
@@ -1022,45 +1025,45 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, parser_helper_t *c
switch (yytype)
{
case 3: /* NAME */
-#line 90 "settings/settings_parser.y" /* yacc.c:1257 */
+#line 91 "settings/settings_parser.y" /* yacc.c:1257 */
{ free(((*yyvaluep).s)); }
-#line 1028 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1031 "settings/settings_parser.c" /* yacc.c:1257 */
break;
case 4: /* STRING */
-#line 90 "settings/settings_parser.y" /* yacc.c:1257 */
+#line 91 "settings/settings_parser.y" /* yacc.c:1257 */
{ free(((*yyvaluep).s)); }
-#line 1034 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1037 "settings/settings_parser.c" /* yacc.c:1257 */
break;
- case 12: /* section */
-#line 92 "settings/settings_parser.y" /* yacc.c:1257 */
+ case 13: /* section */
+#line 93 "settings/settings_parser.y" /* yacc.c:1257 */
{ pop_section(ctx); settings_section_destroy(((*yyvaluep).sec), NULL); }
-#line 1040 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1043 "settings/settings_parser.c" /* yacc.c:1257 */
break;
- case 13: /* section_start */
-#line 92 "settings/settings_parser.y" /* yacc.c:1257 */
+ case 14: /* section_start */
+#line 93 "settings/settings_parser.y" /* yacc.c:1257 */
{ pop_section(ctx); settings_section_destroy(((*yyvaluep).sec), NULL); }
-#line 1046 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1049 "settings/settings_parser.c" /* yacc.c:1257 */
break;
- case 14: /* setting */
-#line 93 "settings/settings_parser.y" /* yacc.c:1257 */
+ case 15: /* setting */
+#line 94 "settings/settings_parser.y" /* yacc.c:1257 */
{ settings_kv_destroy(((*yyvaluep).kv), NULL); }
-#line 1052 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1055 "settings/settings_parser.c" /* yacc.c:1257 */
break;
- case 15: /* value */
-#line 90 "settings/settings_parser.y" /* yacc.c:1257 */
+ case 16: /* value */
+#line 91 "settings/settings_parser.y" /* yacc.c:1257 */
{ free(((*yyvaluep).s)); }
-#line 1058 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1061 "settings/settings_parser.c" /* yacc.c:1257 */
break;
- case 16: /* valuepart */
-#line 90 "settings/settings_parser.y" /* yacc.c:1257 */
+ case 17: /* valuepart */
+#line 91 "settings/settings_parser.y" /* yacc.c:1257 */
{ free(((*yyvaluep).s)); }
-#line 1064 "settings/settings_parser.c" /* yacc.c:1257 */
+#line 1067 "settings/settings_parser.c" /* yacc.c:1257 */
break;
@@ -1326,64 +1329,64 @@ yyreduce:
switch (yyn)
{
case 5:
-#line 112 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 113 "settings/settings_parser.y" /* yacc.c:1646 */
{
add_section(ctx, (yyvsp[0].sec));
}
-#line 1334 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1337 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 6:
-#line 116 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 117 "settings/settings_parser.y" /* yacc.c:1646 */
{
add_setting(ctx, (yyvsp[0].kv));
}
-#line 1342 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1345 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 7:
-#line 123 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 124 "settings/settings_parser.y" /* yacc.c:1646 */
{
pop_section(ctx);
(yyval.sec) = (yyvsp[-2].sec);
}
-#line 1351 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1354 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 8:
-#line 131 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 132 "settings/settings_parser.y" /* yacc.c:1646 */
{
(yyval.sec) = push_section(ctx, (yyvsp[-1].s));
}
-#line 1359 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1362 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 9:
-#line 136 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 137 "settings/settings_parser.y" /* yacc.c:1646 */
{
(yyval.sec) = push_section(ctx, (yyvsp[-2].s));
}
-#line 1367 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1370 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 10:
-#line 143 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 144 "settings/settings_parser.y" /* yacc.c:1646 */
{
(yyval.kv) = settings_kv_create((yyvsp[-2].s), (yyvsp[0].s));
}
-#line 1375 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1378 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 11:
-#line 148 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 149 "settings/settings_parser.y" /* yacc.c:1646 */
{
(yyval.kv) = settings_kv_create((yyvsp[-1].s), NULL);
}
-#line 1383 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1386 "settings/settings_parser.c" /* yacc.c:1646 */
break;
case 13:
-#line 156 "settings/settings_parser.y" /* yacc.c:1646 */
+#line 157 "settings/settings_parser.y" /* yacc.c:1646 */
{ /* just put a single space between them, use strings for more */
if (asprintf(&(yyval.s), "%s %s", (yyvsp[-1].s), (yyvsp[0].s)) < 0)
{
@@ -1394,11 +1397,11 @@ yyreduce:
free((yyvsp[-1].s));
free((yyvsp[0].s));
}
-#line 1398 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1401 "settings/settings_parser.c" /* yacc.c:1646 */
break;
-#line 1402 "settings/settings_parser.c" /* yacc.c:1646 */
+#line 1405 "settings/settings_parser.c" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
@@ -1626,7 +1629,7 @@ yyreturn:
#endif
return yyresult;
}
-#line 173 "settings/settings_parser.y" /* yacc.c:1906 */
+#line 174 "settings/settings_parser.y" /* yacc.c:1906 */
/**
@@ -1743,3 +1746,39 @@ bool settings_parser_parse_file(section_t *root, char *name)
helper->destroy(helper);
return success;
}
+
+/**
+ * Parse the given string and add all sections and key/value pairs to the
+ * given section.
+ */
+bool settings_parser_parse_string(section_t *root, char *settings)
+{
+ parser_helper_t *helper;
+ array_t *sections = NULL;
+ bool success = FALSE;
+
+ array_insert_create(&sections, ARRAY_TAIL, root);
+ helper = parser_helper_create(sections);
+ helper->get_lineno = settings_parser_get_lineno;
+ if (settings_parser_lex_init_extra(helper, &helper->scanner) != 0)
+ {
+ helper->destroy(helper);
+ array_destroy(sections);
+ return FALSE;
+ }
+ settings_parser_load_string(helper, settings);
+ if (getenv("DEBUG_SETTINGS_PARSER"))
+ {
+ yydebug = 1;
+ settings_parser_set_debug(1, helper->scanner);
+ }
+ success = yyparse(helper) == 0;
+ if (!success)
+ {
+ DBG1(DBG_CFG, "failed to parse settings '%s'", settings);
+ }
+ array_destroy(sections);
+ settings_parser_lex_destroy(helper->scanner);
+ helper->destroy(helper);
+ return success;
+}
diff --git a/src/libstrongswan/settings/settings_parser.h b/src/libstrongswan/settings/settings_parser.h
index 9d56465ef..d887777a2 100644
--- a/src/libstrongswan/settings/settings_parser.h
+++ b/src/libstrongswan/settings/settings_parser.h
@@ -47,26 +47,28 @@ extern int settings_parser_debug;
{
NAME = 258,
STRING = 259,
- NEWLINE = 260
+ NEWLINE = 260,
+ STRING_ERROR = 261
};
#endif
/* Tokens. */
#define NAME 258
#define STRING 259
#define NEWLINE 260
+#define STRING_ERROR 261
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
typedef union YYSTYPE YYSTYPE;
union YYSTYPE
{
-#line 76 "settings/settings_parser.y" /* yacc.c:1909 */
+#line 77 "settings/settings_parser.y" /* yacc.c:1909 */
char *s;
struct section_t *sec;
struct kv_t *kv;
-#line 70 "settings/settings_parser.h" /* yacc.c:1909 */
+#line 72 "settings/settings_parser.h" /* yacc.c:1909 */
};
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
diff --git a/src/libstrongswan/settings/settings_parser.y b/src/libstrongswan/settings/settings_parser.y
index d95a24b2a..96ab36faf 100644
--- a/src/libstrongswan/settings/settings_parser.y
+++ b/src/libstrongswan/settings/settings_parser.y
@@ -39,6 +39,7 @@ int settings_parser_get_leng(void *scanner);
int settings_parser_get_lineno(void *scanner);
/* Custom functions in lexer */
bool settings_parser_open_next_file(parser_helper_t *ctx);
+bool settings_parser_load_string(parser_helper_t *ctx, const char *content);
/**
* Forward declarations
@@ -79,7 +80,7 @@ static int yylex(YYSTYPE *lvalp, parser_helper_t *ctx)
struct kv_t *kv;
}
%token <s> NAME STRING
-%token NEWLINE
+%token NEWLINE STRING_ERROR
/* ...and other symbols */
%type <s> value valuepart
@@ -286,3 +287,39 @@ bool settings_parser_parse_file(section_t *root, char *name)
helper->destroy(helper);
return success;
}
+
+/**
+ * Parse the given string and add all sections and key/value pairs to the
+ * given section.
+ */
+bool settings_parser_parse_string(section_t *root, char *settings)
+{
+ parser_helper_t *helper;
+ array_t *sections = NULL;
+ bool success = FALSE;
+
+ array_insert_create(&sections, ARRAY_TAIL, root);
+ helper = parser_helper_create(sections);
+ helper->get_lineno = settings_parser_get_lineno;
+ if (settings_parser_lex_init_extra(helper, &helper->scanner) != 0)
+ {
+ helper->destroy(helper);
+ array_destroy(sections);
+ return FALSE;
+ }
+ settings_parser_load_string(helper, settings);
+ if (getenv("DEBUG_SETTINGS_PARSER"))
+ {
+ yydebug = 1;
+ settings_parser_set_debug(1, helper->scanner);
+ }
+ success = yyparse(helper) == 0;
+ if (!success)
+ {
+ DBG1(DBG_CFG, "failed to parse settings '%s'", settings);
+ }
+ array_destroy(sections);
+ settings_parser_lex_destroy(helper->scanner);
+ helper->destroy(helper);
+ return success;
+}
diff --git a/src/libstrongswan/tests/suites/test_chunk.c b/src/libstrongswan/tests/suites/test_chunk.c
index 312a187ac..6272ca795 100644
--- a/src/libstrongswan/tests/suites/test_chunk.c
+++ b/src/libstrongswan/tests/suites/test_chunk.c
@@ -1020,7 +1020,7 @@ START_TEST(test_printf_hook)
int len;
/* %B should be the same as %b, which is what we check, comparing the
- * acutal result could be tricky as %b prints the chunk's memory address */
+ * actual result could be tricky as %b prints the chunk's memory address */
len = snprintf(buf, sizeof(buf), "%B", &printf_hook_data[_i].in);
ck_assert(len >= 0 && len < sizeof(buf));
len = snprintf(mem, sizeof(mem), "%b", printf_hook_data[_i].in.ptr,
diff --git a/src/libstrongswan/tests/suites/test_host.c b/src/libstrongswan/tests/suites/test_host.c
index 7161b2c5b..5cb8013ff 100644
--- a/src/libstrongswan/tests/suites/test_host.c
+++ b/src/libstrongswan/tests/suites/test_host.c
@@ -104,6 +104,9 @@ START_TEST(test_create_from_string_v4)
{
host_t *host;
+ host = host_create_from_string(NULL, 500);
+ ck_assert(!host);
+
host = host_create_from_string("%any", 500);
verify_any(host, AF_INET, 500);
host->destroy(host);
@@ -196,6 +199,7 @@ static void test_create_from_string_and_family_addr(char *string, chunk_t addr,
START_TEST(test_create_from_string_and_family_v4)
{
+ test_create_from_string_and_family_any(NULL, AF_INET, AF_UNSPEC);
test_create_from_string_and_family_any("%any", AF_INET, AF_INET);
test_create_from_string_and_family_any("%any4", AF_INET, AF_INET);
test_create_from_string_and_family_any("0.0.0.0", AF_INET, AF_INET);
@@ -210,6 +214,7 @@ END_TEST
START_TEST(test_create_from_string_and_family_v6)
{
+ test_create_from_string_and_family_any(NULL, AF_INET6, AF_UNSPEC);
test_create_from_string_and_family_any("%any", AF_INET6, AF_INET6);
test_create_from_string_and_family_any("%any6", AF_INET6, AF_INET6);
test_create_from_string_and_family_any("::", AF_INET6, AF_INET6);
@@ -224,6 +229,7 @@ END_TEST
START_TEST(test_create_from_string_and_family_other)
{
+ test_create_from_string_and_family_any(NULL, AF_UNSPEC, AF_UNSPEC);
test_create_from_string_and_family_any("%any", AF_UNSPEC, AF_INET);
test_create_from_string_and_family_any("%any4", AF_UNSPEC, AF_INET);
test_create_from_string_and_family_any("0.0.0.0", AF_UNSPEC, AF_INET);
diff --git a/src/libstrongswan/tests/suites/test_identification.c b/src/libstrongswan/tests/suites/test_identification.c
index de00e4afd..ff14ba897 100644
--- a/src/libstrongswan/tests/suites/test_identification.c
+++ b/src/libstrongswan/tests/suites/test_identification.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Tobias Brunner
+ * Copyright (C) 2013-2015 Tobias Brunner
* Copyright (C) 2009 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -727,6 +727,88 @@ START_TEST(test_matches_empty_reverse)
END_TEST
/*******************************************************************************
+ * identification hashing
+ */
+
+static bool id_hash_equals(char *str, char *b_str)
+{
+ identification_t *a, *b;
+ bool success = FALSE;
+
+ a = identification_create_from_string(str);
+ b = identification_create_from_string(b_str ?: str);
+ success = a->hash(a, 0) == b->hash(b, 0);
+ a->destroy(a);
+ b->destroy(b);
+ return success;
+}
+
+START_TEST(test_hash)
+{
+ ck_assert(id_hash_equals("moon@strongswan.org", NULL));
+ ck_assert(id_hash_equals("vpn.strongswan.org", NULL));
+ ck_assert(id_hash_equals("192.168.1.1", NULL));
+ ck_assert(id_hash_equals("C=CH", NULL));
+
+ ck_assert(!id_hash_equals("moon@strongswan.org", "sun@strongswan.org"));
+ ck_assert(!id_hash_equals("vpn.strongswan.org", "*.strongswan.org"));
+ ck_assert(!id_hash_equals("192.168.1.1", "192.168.1.2"));
+ ck_assert(!id_hash_equals("C=CH", "C=DE"));
+ ck_assert(!id_hash_equals("fqdn:strongswan.org", "keyid:strongswan.org"));
+}
+END_TEST
+
+START_TEST(test_hash_any)
+{
+ ck_assert(id_hash_equals("%any", NULL));
+ ck_assert(id_hash_equals("%any", "0.0.0.0"));
+ ck_assert(id_hash_equals("%any", "*"));
+ ck_assert(id_hash_equals("%any", ""));
+
+ ck_assert(!id_hash_equals("%any", "any"));
+}
+END_TEST
+
+START_TEST(test_hash_dn)
+{
+ identification_t *a, *b;
+
+ /* same DN (C=CH, O=strongSwan), different RDN type (PRINTABLESTRING vs.
+ * UTF8STRING) */
+ a = identification_create_from_data(chunk_from_chars(
+ 0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x13, 0x02, 0x43, 0x48, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x13, 0x0a, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67,
+ 0x53, 0x77, 0x61, 0x6e));
+ b = identification_create_from_data(chunk_from_chars(
+ 0x30, 0x22, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
+ 0x55, 0x04, 0x06, 0x0c, 0x02, 0x43, 0x48, 0x31,
+ 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0a,
+ 0x0c, 0x0a, 0x73, 0x74, 0x72, 0x6f, 0x6e, 0x67,
+ 0x53, 0x77, 0x61, 0x6e));
+ ck_assert_int_eq(a->hash(a, 0), b->hash(b, 0));
+ ck_assert(a->equals(a, b));
+ a->destroy(a);
+ b->destroy(b);
+}
+END_TEST
+
+START_TEST(test_hash_inc)
+{
+ identification_t *a;
+
+ a = identification_create_from_string("vpn.strongswan.org");
+ ck_assert(a->hash(a, 0) != a->hash(a, 1));
+ a->destroy(a);
+
+ a = identification_create_from_string("C=CH, O=strongSwan");
+ ck_assert(a->hash(a, 0) != a->hash(a, 1));
+ a->destroy(a);
+}
+END_TEST
+
+/*******************************************************************************
* identification part enumeration
*/
@@ -851,6 +933,13 @@ Suite *identification_suite_create()
tcase_add_loop_test(tc, test_matches_empty_reverse, ID_ANY, ID_KEY_ID + 1);
suite_add_tcase(s, tc);
+ tc = tcase_create("hash");
+ tcase_add_test(tc, test_hash);
+ tcase_add_test(tc, test_hash_any);
+ tcase_add_test(tc, test_hash_dn);
+ tcase_add_test(tc, test_hash_inc);
+ suite_add_tcase(s, tc);
+
tc = tcase_create("part enumeration");
tcase_add_test(tc, test_parts);
suite_add_tcase(s, tc);
diff --git a/src/libstrongswan/tests/suites/test_settings.c b/src/libstrongswan/tests/suites/test_settings.c
index 9601a34a9..bead9d795 100644
--- a/src/libstrongswan/tests/suites/test_settings.c
+++ b/src/libstrongswan/tests/suites/test_settings.c
@@ -58,6 +58,10 @@ START_SETUP(setup_base_config)
" }\n"
" key2 = with space\n"
" key3 = \"string with\\nnewline\"\n"
+ " key4 = \"multi line\n"
+ "string\"\n"
+ " key5 = \"escaped \\\n"
+ "newline\"\n"
"}\n"
"out = side\n"
"other {\n"
@@ -88,6 +92,8 @@ START_TEST(test_get_str)
verify_string("", "main.empty");
verify_string("with space", "main.key2");
verify_string("string with\nnewline", "main.key3");
+ verify_string("multi line\nstring", "main.key4");
+ verify_string("escaped newline", "main.key5");
verify_string("value", "main.sub1.key");
verify_string("value2", "main.sub1.key2");
verify_string("bar", "main.sub1.subsub.foo");
@@ -97,7 +103,7 @@ START_TEST(test_get_str)
verify_string("other val", "other.key1");
verify_null("main.none");
- verify_null("main.key4");
+ verify_null("main.key6");
verify_null("other.sub");
}
END_TEST
@@ -131,7 +137,7 @@ START_TEST(test_get_str_printf)
* probably document it at least */
verify_null("main.%s%u.key%d", "sub", 1, 2);
- verify_null("%s.%s%d", "main", "key", 4);
+ verify_null("%s.%s%d", "main", "key", 6);
}
END_TEST
@@ -529,9 +535,7 @@ END_TEST
# define include2 "/tmp/strongswan-settings-test-include2"
#endif
-START_SETUP(setup_include_config)
-{
- chunk_t inc1 = chunk_from_str(
+static char *include_content1 =
"main {\n"
" key1 = n1\n"
" key2 = n2\n"
@@ -544,14 +548,17 @@ START_SETUP(setup_include_config)
" sub3 = val3\n"
" }\n"
" include " include2 "\n"
- "}");
- chunk_t inc2 = chunk_from_str(
+ "}";
+static char *include_content2 =
"key2 = v2\n"
"sub1 {\n"
" key = val\n"
- "}");
- ck_assert(chunk_write(inc1, include1, 0022, TRUE));
- ck_assert(chunk_write(inc2, include2, 0022, TRUE));
+ "}";
+
+START_SETUP(setup_include_config)
+{
+ ck_assert(chunk_write(chunk_from_str(include_content1), include1, 0022, TRUE));
+ ck_assert(chunk_write(chunk_from_str(include_content2), include2, 0022, TRUE));
}
END_SETUP
@@ -600,6 +607,27 @@ START_TEST(test_include)
}
END_TEST
+START_TEST(test_include_string)
+{
+ chunk_t contents = chunk_from_str(
+ "main {\n"
+ " key1 = val1\n"
+ " key2 = val2\n"
+ " none = x\n"
+ " sub1 {\n"
+ " include this/does/not/exist.conf\n"
+ " include = value\n"
+ " key2 = value2\n"
+ " include \"" include2 "\"\n"
+ " }\n"
+ "}\n"
+ "include \"" include1 "\"");
+
+ create_settings(contents);
+ verify_include();
+}
+END_TEST
+
START_TEST(test_load_files)
{
chunk_t contents = chunk_from_str(
@@ -784,6 +812,104 @@ START_TEST(test_order_section)
}
END_TEST
+
+START_TEST(test_load_string)
+{
+ char *content =
+ "main {\n"
+ " key1 = val1\n"
+ " key2 = val2\n"
+ " key3 = val3\n"
+ " none = x\n"
+ " sub1 {\n"
+ " include = value\n"
+ " key2 = v2\n"
+ " sub1 {\n"
+ " key = val\n"
+ " }\n"
+ " }\n"
+ "}";
+ char *val1, *val2, *val3;
+
+ settings = settings_create_string(content);
+
+ val1 = settings->get_str(settings, "main.key1", NULL);
+ val2 = settings->get_str(settings, "main.sub1.key2", NULL);
+ /* loading the same content twice should not change anything, with... */
+ ck_assert(settings->load_string(settings, content, TRUE));
+ ck_assert(val1 == settings->get_str(settings, "main.key1", NULL));
+ ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL));
+ /* ...or without merging */
+ ck_assert(settings->load_string(settings, content, FALSE));
+ ck_assert(val1 == settings->get_str(settings, "main.key1", NULL));
+ ck_assert(val2 == settings->get_str(settings, "main.sub1.key2", NULL));
+
+ val1 = settings->get_str(settings, "main.key2", NULL);
+ val2 = settings->get_str(settings, "main.key3", NULL);
+ val3 = settings->get_str(settings, "main.none", NULL);
+ /* only pointers for modified settings should change, but still be valid */
+ ck_assert(settings->load_string(settings, include_content1, FALSE));
+ ck_assert(val1 != settings->get_str(settings, "main.key2", NULL));
+ ck_assert_str_eq(val1, "val2");
+ ck_assert(val2 == settings->get_str(settings, "main.key3", NULL));
+ ck_assert(val3 != settings->get_str(settings, "main.none", NULL));
+ ck_assert_str_eq(val3, "x");
+
+ settings->destroy(settings);
+ settings = settings_create_string(content);
+ ck_assert(settings);
+
+ ck_assert(settings->load_string(settings, include_content1, TRUE));
+ verify_include();
+
+ ck_assert(settings->load_string(settings, include_content2, FALSE));
+ verify_null("main.key1");
+ verify_string("v2", "key2");
+ verify_string("val", "sub1.key");
+ verify_null("main.sub1.key3");
+}
+END_TEST
+
+
+START_TEST(test_load_string_section)
+{
+ char *content =
+ "main {\n"
+ " key1 = val1\n"
+ " key2 = val2\n"
+ " none = x\n"
+ " sub1 {\n"
+ " include = value\n"
+ " key2 = value2\n"
+ " }\n"
+ "}";
+
+ settings = settings_create_string(content);
+
+ ck_assert(settings->load_string_section(settings, include_content1, TRUE, ""));
+ ck_assert(settings->load_string_section(settings, include_content2, TRUE, "main.sub1"));
+ verify_include();
+
+ /* invalid strings are a failure */
+ ck_assert(!settings->load_string_section(settings, "conf {", TRUE, ""));
+ /* NULL or empty strings are OK though */
+ ck_assert(settings->load_string_section(settings, "", TRUE, ""));
+ ck_assert(settings->load_string_section(settings, NULL, TRUE, ""));
+ verify_include();
+
+ ck_assert(settings->load_string_section(settings, include_content2, FALSE, "main"));
+ verify_null("main.key1");
+ verify_string("v2", "main.key2");
+ verify_string("val", "main.sub1.key");
+ verify_null("main.sub1.key3");
+ verify_null("main.sub2.sub3");
+
+ ck_assert(settings->load_string_section(settings, include_content2, TRUE, "main.sub2"));
+ verify_string("v2", "main.sub2.key2");
+ verify_string("val", "main.sub2.sub1.key");
+}
+END_TEST
+
START_SETUP(setup_fallback_config)
{
create_settings(chunk_from_str(
@@ -904,11 +1030,10 @@ END_TEST
START_SETUP(setup_string_config)
{
create_settings(chunk_from_str(
- "string = \" with accurate\twhitespace\"\n"
+ "string = \" with accurate\twhite\\tspace\"\n"
"special = \"all { special } characters # can be used.\"\n"
- "unterminated = \"is fine\n"
- "but = produces a warning\n"
- "newlines = \"can either be encoded\\nor \\\n"
+ "newlines = \"can be encoded explicitly\\nor implicitly\n"
+ "or \\\n"
"escaped\"\n"
"quotes = \"\\\"and\\\" slashes \\\\ can \\\\ be\" # escaped too\n"
"multiple = \"strings\" are \"combined\"\n"
@@ -918,11 +1043,9 @@ END_SETUP
START_TEST(test_strings)
{
- verify_string(" with accurate\twhitespace", "string");
+ verify_string(" with accurate\twhite\tspace", "string");
verify_string("all { special } characters # can be used.", "special");
- verify_string("is fine", "unterminated");
- verify_string("produces a warning", "but");
- verify_string("can either be encoded\nor escaped", "newlines");
+ verify_string("can be encoded explicitly\nor implicitly\nor escaped", "newlines");
verify_string("\"and\" slashes \\ can \\ be", "quotes");
verify_string("strings are combined", "multiple");
}
@@ -990,6 +1113,12 @@ START_TEST(test_invalid)
ck_assert(!settings->load_files(settings, path, FALSE));
contents = chunk_from_str(
+ "unterminated {\n"
+ " strings = \"are invalid\n");
+ ck_assert(chunk_write(contents, path, 0022, TRUE));
+ ck_assert(!settings->load_files(settings, path, FALSE));
+
+ contents = chunk_from_str(
"spaces in name {}");
ck_assert(chunk_write(contents, path, 0022, TRUE));
ck_assert(!settings->load_files(settings, path, FALSE));
@@ -1054,12 +1183,19 @@ Suite *settings_suite_create()
tc = tcase_create("include/load_files[_section]");
tcase_add_checked_fixture(tc, setup_include_config, teardown_include_config);
tcase_add_test(tc, test_include);
+ tcase_add_test(tc, test_include_string);
tcase_add_test(tc, test_load_files);
tcase_add_test(tc, test_load_files_section);
tcase_add_test(tc, test_order_kv);
tcase_add_test(tc, test_order_section);
suite_add_tcase(s, tc);
+ tc = tcase_create("load_string[_section]");
+ tcase_add_checked_fixture(tc, setup_include_config, teardown_config);
+ tcase_add_test(tc, test_load_string);
+ tcase_add_test(tc, test_load_string_section);
+ suite_add_tcase(s, tc);
+
tc = tcase_create("fallback");
tcase_add_checked_fixture(tc, setup_fallback_config, teardown_config);
tcase_add_test(tc, test_add_fallback);
diff --git a/src/libstrongswan/tests/suites/test_traffic_selector.c b/src/libstrongswan/tests/suites/test_traffic_selector.c
index 4312c6ce1..bec32d2d8 100644
--- a/src/libstrongswan/tests/suites/test_traffic_selector.c
+++ b/src/libstrongswan/tests/suites/test_traffic_selector.c
@@ -1,4 +1,7 @@
/*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
* Copyright (C) 2015 Martin Willi
* Copyright (C) 2015 revosec AG
*
@@ -22,10 +25,9 @@ static void verify(const char *str, const char *alt, traffic_selector_t *ts)
{
char buf[512];
- ck_assert(ts != NULL);
snprintf(buf, sizeof(buf), "%R", ts);
- ts->destroy(ts);
- if (!streq(buf, str) && !streq(buf, alt))
+ DESTROY_IF(ts);
+ if (!streq(buf, str) && (!alt || !streq(buf, alt)))
{
fail("%s != %s or %s", buf, str, alt);
}
@@ -43,6 +45,16 @@ START_TEST(test_create_from_string)
verify("fec1::/64", NULL,
traffic_selector_create_from_string(0, TS_IPV6_ADDR_RANGE,
"fec1::", 0, "fec1::ffff:ffff:ffff:ffff", 65535));
+ verify("fec1::1..fec1::ffff:ffff:ffff:ffff", NULL,
+ traffic_selector_create_from_string(0, TS_IPV6_ADDR_RANGE,
+ "fec1::1", 0, "fec1::ffff:ffff:ffff:ffff", 65535));
+
+ ck_assert(!traffic_selector_create_from_string(IPPROTO_TCP, 0,
+ "10.1.0.0", 80, "10.1.255.255", 80));
+ ck_assert(!traffic_selector_create_from_string(IPPROTO_TCP, TS_IPV4_ADDR_RANGE,
+ "a.b.c.d", 80, "10.1.255.255", 80));
+ ck_assert(!traffic_selector_create_from_string(IPPROTO_TCP, TS_IPV4_ADDR_RANGE,
+ "10.1.0.0", 80, "a.b.c.d", 80));
}
END_TEST
@@ -53,6 +65,10 @@ START_TEST(test_create_from_cidr)
verify("10.1.0.1/32[udp/1234-1235]", "10.1.0.1/32[17/1234-1235]",
traffic_selector_create_from_cidr("10.1.0.1/32", IPPROTO_UDP,
1234, 1235));
+ verify("10.1.0.0/16[OPAQUE]", NULL,
+ traffic_selector_create_from_cidr("10.1.0.0/16", 0, 65535, 0));
+
+ ck_assert(!traffic_selector_create_from_cidr("a.b.c.d/16", 0, 0, 65535));
}
END_TEST
@@ -62,6 +78,16 @@ START_TEST(test_create_from_bytes)
traffic_selector_create_from_bytes(0, TS_IPV4_ADDR_RANGE,
chunk_from_chars(0x0a,0x01,0x00,0x00), 0,
chunk_from_chars(0x0a,0x01,0xff,0xff), 65535));
+
+ ck_assert(!traffic_selector_create_from_bytes(0, TS_IPV4_ADDR_RANGE,
+ chunk_empty, 0,
+ chunk_empty, 65535));
+ ck_assert(!traffic_selector_create_from_bytes(0, TS_IPV6_ADDR_RANGE,
+ chunk_from_chars(0x0a,0x01,0x00,0x00), 0,
+ chunk_from_chars(0x0a,0x01,0xff,0xff), 65535));
+ ck_assert(!traffic_selector_create_from_bytes(0, 0,
+ chunk_from_chars(0x0a,0x01,0x00,0x00), 0,
+ chunk_from_chars(0x0a,0x01,0xff,0xff), 65535));
}
END_TEST
@@ -73,6 +99,175 @@ START_TEST(test_create_from_subnet)
}
END_TEST
+struct {
+ char *net;
+ ts_type_t type;
+ chunk_t enc;
+} rfc3779_prefix_tests[] = {
+ /* some examples from RFC 3779, for addressPrefix elements we pass the same
+ * value twice to the constructor */
+ { "10.0.0.0/8", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x00,0x0a), },
+ { "10.0.32.0/20", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x04,0x0a,0x00,0x20), },
+ { "10.0.64.0/24", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x00,0x0a,0x00,0x40), },
+ { "10.1.0.0/16", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x00,0x0a,0x01), },
+ { "10.5.0.1/32", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x00,0x0a,0x05,0x00,0x01), },
+ { "10.5.0.0/23", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x01,0x0a,0x05,0x00), },
+ { "10.64.0.0/12", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x04,0x0a,0x40), },
+ { "10.64.0.0/20", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x04,0x0a,0x40,0x00), },
+ { "128.0.0.0/4", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x04,0x80), },
+ { "172.16.0.0/12", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x04,0xac,0x10), },
+ { "0.0.0.0/0", TS_IPV4_ADDR_RANGE, chunk_from_chars(0x00), },
+ /* FIXME: not a correct encoding, so we might want to fail here */
+ { "0.0.0.0/0", TS_IPV4_ADDR_RANGE, {NULL, 0}, },
+ { "2001:0:2::/48", TS_IPV6_ADDR_RANGE, chunk_from_chars(0x00,0x20,0x01,0x00,0x00,0x00,0x02),},
+ { "2001:0:200::/39",TS_IPV6_ADDR_RANGE, chunk_from_chars(0x01,0x20,0x01,0x00,0x00,0x02),},
+ { "::/0", TS_IPV6_ADDR_RANGE, chunk_from_chars(0x00), },
+ /* FIXME: not a correct encoding, so we might want to fail here */
+ { "::/0", TS_IPV6_ADDR_RANGE, {NULL, 0}, },
+};
+
+START_TEST(test_create_from_rfc3779_format_prefix)
+{
+ verify(rfc3779_prefix_tests[_i].net, NULL,
+ traffic_selector_create_from_rfc3779_format(rfc3779_prefix_tests[_i].type,
+ rfc3779_prefix_tests[_i].enc, rfc3779_prefix_tests[_i].enc));
+}
+END_TEST
+
+START_TEST(test_create_from_rfc3779_format_range)
+{
+ /* addressRange elements encode a from and to address, which may still
+ * represent prefixes */
+ verify("10.5.0.0/23", NULL,
+ traffic_selector_create_from_rfc3779_format(TS_IPV4_ADDR_RANGE,
+ chunk_from_chars(0x00,0x0a,0x05),
+ chunk_from_chars(0x01,0x0a,0x05,0x00)));
+ verify("2001:0:200::/39", NULL,
+ traffic_selector_create_from_rfc3779_format(TS_IPV6_ADDR_RANGE,
+ chunk_from_chars(0x01,0x20,0x01,0x00,0x00,0x02),
+ chunk_from_chars(0x02,0x20,0x01,0x00,0x00,0x00)));
+ verify("10.2.48.0..10.2.64.255", NULL,
+ traffic_selector_create_from_rfc3779_format(TS_IPV4_ADDR_RANGE,
+ chunk_from_chars(0x04,0x0a,0x02,0x30),
+ chunk_from_chars(0x00,0x0a,0x02,0x40)));
+ verify("129.64.0.0..143.255.255.255", NULL,
+ traffic_selector_create_from_rfc3779_format(TS_IPV4_ADDR_RANGE,
+ chunk_from_chars(0x06,0x81,0x40),
+ chunk_from_chars(0x04,0x80)));
+}
+END_TEST
+
+
+static void verify_address(char *addr_from, char *addr_to, traffic_selector_t *ts)
+{
+ host_t *from, *to;
+
+ from = host_create_from_string(addr_from, 0);
+ to = host_create_from_string(addr_to, 0);
+
+ ck_assert_chunk_eq(from->get_address(from), ts->get_from_address(ts));
+ ck_assert_chunk_eq(to->get_address(to), ts->get_to_address(ts));
+ from->destroy(from);
+ to->destroy(to);
+ ts->destroy(ts);
+}
+
+START_TEST(test_get_address_range)
+{
+ verify_address("10.1.0.1", "10.1.0.10",
+ traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE,
+ "10.1.0.1", 0, "10.1.0.10", 65535));
+ /* currently not reordered */
+ verify_address("10.1.0.10", "10.1.0.1",
+ traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE,
+ "10.1.0.10", 0, "10.1.0.1", 65535));
+}
+END_TEST
+
+START_TEST(test_get_address_cidr)
+{
+ verify_address("10.1.0.0", "10.1.255.255",
+ traffic_selector_create_from_cidr("10.1.0.0/16", 0, 0, 65535));
+ verify_address("fec1::", "fec1::ffff:ffff:ffff:ffff",
+ traffic_selector_create_from_cidr("fec1::/64", 0, 0, 65535));
+}
+END_TEST
+
+struct {
+ ts_type_t type;
+ char *from;
+ char *to;
+ char *net;
+ u_int8_t mask;
+ bool exact;
+} to_subnet_tests[] = {
+ { TS_IPV4_ADDR_RANGE, "10.0.0.1", "10.0.0.1", "10.0.0.1", 32, TRUE },
+ { TS_IPV4_ADDR_RANGE, "10.0.0.0", "10.255.255.255", "10.0.0.0", 8, TRUE },
+ { TS_IPV4_ADDR_RANGE, "10.0.0.1", "10.0.0.255", "10.0.0.0", 24, FALSE },
+ { TS_IPV4_ADDR_RANGE, "10.0.0.0", "10.0.0.15", "10.0.0.0", 28, TRUE },
+ { TS_IPV4_ADDR_RANGE, "10.0.0.1", "10.0.0.15", "10.0.0.0", 28, FALSE },
+ { TS_IPV4_ADDR_RANGE, "10.0.0.1", "10.0.0.16", "10.0.0.0", 27, FALSE },
+ { TS_IPV6_ADDR_RANGE, "fec1::1", "fec1::1", "fec1::1", 128, TRUE },
+ { TS_IPV6_ADDR_RANGE, "fec1::0", "fec1::ffff:ffff:ffff:ffff", "fec1::", 64, TRUE },
+ { TS_IPV6_ADDR_RANGE, "fec1::1", "fec1::ffff:ffff:ffff:ffff", "fec1::", 64, FALSE },
+ { TS_IPV6_ADDR_RANGE, "fec1::1", "fec1::7fff", "fec1::", 113, FALSE },
+ { TS_IPV6_ADDR_RANGE, "fec1::1", "fec1::efff", "fec1::", 112, FALSE },
+};
+
+START_TEST(test_to_subnet)
+{
+ traffic_selector_t *ts;
+ host_t *net, *exp_net;
+ u_int8_t mask;
+
+ ts = traffic_selector_create_from_string(0, to_subnet_tests[_i].type,
+ to_subnet_tests[_i].from, 0, to_subnet_tests[_i].to, 0);
+ ck_assert(ts->to_subnet(ts, &net, &mask) == to_subnet_tests[_i].exact);
+ exp_net = host_create_from_string(to_subnet_tests[_i].net, 0);
+ ck_assert(exp_net->ip_equals(exp_net, net));
+ ck_assert_int_eq(to_subnet_tests[_i].mask, mask);
+ exp_net->destroy(exp_net);
+ net->destroy(net);
+ ts->destroy(ts);
+}
+END_TEST
+
+struct {
+ char *cidr;
+ u_int16_t from_port;
+ u_int16_t to_port;
+ u_int16_t port;
+} to_subnet_port_tests[] = {
+ { "10.0.0.0/8", 0, 0, 0 },
+ { "10.0.0.1/32", 80, 80, 80 },
+ { "10.0.0.1/32", 123, 465, 0 },
+ { "0.0.0.0/0", 0, 65535, 0 },
+ { "fec1::/64", 0, 0, 0 },
+ { "fec1::1/128", 80, 80, 80 },
+ { "fec1::1/128", 123, 465, 0 },
+ { "::/0", 0, 65535, 0 },
+};
+
+START_TEST(test_to_subnet_port)
+{
+ traffic_selector_t *ts;
+ host_t *net, *exp_net;
+ u_int8_t mask;
+ int exp_mask;
+
+ ts = traffic_selector_create_from_cidr(to_subnet_port_tests[_i].cidr, 0,
+ to_subnet_port_tests[_i].from_port,
+ to_subnet_port_tests[_i].to_port);
+ ck_assert(ts->to_subnet(ts, &net, &mask));
+ exp_net = host_create_from_subnet(to_subnet_port_tests[_i].cidr, &exp_mask);
+ ck_assert(exp_net->ip_equals(exp_net, net));
+ ck_assert_int_eq(exp_mask, mask);
+ ck_assert_int_eq(to_subnet_port_tests[_i].port, net->get_port(net));
+ exp_net->destroy(exp_net);
+ net->destroy(net);
+ ts->destroy(ts);
+}
+END_TEST
START_TEST(test_subset)
{
@@ -81,6 +276,14 @@ START_TEST(test_subset)
a = traffic_selector_create_from_cidr("10.1.0.0/16", 0, 0, 65535);
b = traffic_selector_create_from_cidr("10.1.5.0/24", 0, 0, 65535);
verify("10.1.5.0/24", NULL, a->get_subset(a, b));
+ verify("10.1.5.0/24", NULL, b->get_subset(b, a));
+ a->destroy(a);
+ b->destroy(b);
+
+ a = traffic_selector_create_from_cidr("fec1::/64", 0, 0, 65535);
+ b = traffic_selector_create_from_cidr("fec1::1/128", 0, 0, 65535);
+ verify("fec1::1/128", NULL, a->get_subset(a, b));
+ verify("fec1::1/128", NULL, b->get_subset(b, a));
a->destroy(a);
b->destroy(b);
}
@@ -117,7 +320,7 @@ START_TEST(test_subset_nonet)
a = traffic_selector_create_from_cidr("10.1.0.0/16", 0, 0, 65535);
b = traffic_selector_create_from_cidr("10.2.0.0/16", 0, 0, 65535);
- ck_assert(a->get_subset(a, b) == NULL);
+ ck_assert(!a->get_subset(a, b));
a->destroy(a);
b->destroy(b);
}
@@ -129,7 +332,7 @@ START_TEST(test_subset_noport)
a = traffic_selector_create_from_cidr("10.1.0.0/16", 0, 0, 9999);
b = traffic_selector_create_from_cidr("10.1.0.0/16", 0, 10000, 65535);
- ck_assert(a->get_subset(a, b) == NULL);
+ ck_assert(!a->get_subset(a, b));
a->destroy(a);
b->destroy(b);
}
@@ -141,7 +344,7 @@ START_TEST(test_subset_noproto)
a = traffic_selector_create_from_cidr("10.1.0.0/16", IPPROTO_TCP, 0, 65535);
b = traffic_selector_create_from_cidr("10.1.0.0/16", IPPROTO_UDP, 0, 65535);
- ck_assert(a->get_subset(a, b) == NULL);
+ ck_assert(!a->get_subset(a, b));
a->destroy(a);
b->destroy(b);
}
@@ -153,7 +356,43 @@ START_TEST(test_subset_nofamily)
a = traffic_selector_create_from_cidr("0.0.0.0/0", 0, 0, 65535);
b = traffic_selector_create_from_cidr("::/0", 0, 0, 65535);
- ck_assert(a->get_subset(a, b) == NULL);
+ ck_assert(!a->get_subset(a, b));
+ a->destroy(a);
+ b->destroy(b);
+}
+END_TEST
+
+START_TEST(test_subset_dynamic)
+{
+ traffic_selector_t *a, *b;
+
+ a = traffic_selector_create_dynamic(0, 0, 65535);
+ b = traffic_selector_create_from_cidr("10.1.0.0/16", 0, 0, 65535);
+ ck_assert(!a->get_subset(a, b));
+ ck_assert(!b->get_subset(b, a));
+ a->destroy(a);
+ b->destroy(b);
+}
+END_TEST
+
+START_TEST(test_subset_opaque)
+{
+ traffic_selector_t *a, *b;
+
+ a = traffic_selector_create_from_cidr("10.0.0.0/8", 0, 65535, 0);
+ b = traffic_selector_create_from_cidr("10.2.7.16/30", IPPROTO_TCP, 80, 80);
+ ck_assert(!a->get_subset(a, b));
+ ck_assert(!b->get_subset(b, a));
+ b->destroy(b);
+
+ b = traffic_selector_create_from_cidr("10.2.7.16/30", IPPROTO_TCP, 65535, 0);
+ verify("10.2.7.16/30[tcp/OPAQUE]", "10.2.7.16/30[6/OPAQUE]", a->get_subset(a, b));
+ verify("10.2.7.16/30[tcp/OPAQUE]", "10.2.7.16/30[6/OPAQUE]", b->get_subset(b, a));
+ b->destroy(b);
+
+ b = traffic_selector_create_from_cidr("10.2.7.16/30", IPPROTO_TCP, 0, 65535);
+ verify("10.2.7.16/30[tcp/OPAQUE]", "10.2.7.16/30[6/OPAQUE]", a->get_subset(a, b));
+ verify("10.2.7.16/30[tcp/OPAQUE]", "10.2.7.16/30[6/OPAQUE]", b->get_subset(b, a));
a->destroy(a);
b->destroy(b);
}
@@ -189,6 +428,130 @@ START_TEST(test_includes)
END_TEST
struct {
+ bool contained;
+ struct {
+ char *net;
+ u_int8_t proto;
+ u_int16_t from_port;
+ u_int16_t to_port;
+ } a, b;
+} is_contained_in_tests[] = {
+ { TRUE, { "10.0.0.0/16", 0, 0, 65535 }, { "10.0.0.0/16", 0, 0, 65535 }, },
+ { TRUE, { "10.0.1.0/24", 0, 0, 65535 }, { "10.0.0.0/16", 0, 0, 65535 }, },
+ { TRUE, { "10.0.1.0/24", 17, 123, 456 }, { "10.0.0.0/16", 0, 0, 65535 }, },
+ { TRUE, { "10.0.1.0/24", 17, 123, 456 }, { "10.0.0.0/16", 17, 123, 456 },},
+ { FALSE, { "10.0.0.0/8", 0, 0, 65535 }, { "10.0.0.0/16", 0, 0, 65535 }, },
+ { FALSE, { "10.0.1.0/24", 17, 0, 65535 }, { "10.0.0.0/16", 17, 123, 456 },},
+ { FALSE, { "fec2::/64", 0, 0, 65535 }, { "10.0.0.0/16", 17, 123, 456 },},
+};
+
+START_TEST(test_is_contained_in)
+{
+ traffic_selector_t *a, *b;
+
+ a = traffic_selector_create_from_cidr(
+ is_contained_in_tests[_i].a.net, is_contained_in_tests[_i].a.proto,
+ is_contained_in_tests[_i].a.from_port, is_contained_in_tests[_i].a.to_port);
+ b = traffic_selector_create_from_cidr(
+ is_contained_in_tests[_i].b.net, is_contained_in_tests[_i].b.proto,
+ is_contained_in_tests[_i].b.from_port, is_contained_in_tests[_i].b.to_port);
+ ck_assert(a->is_contained_in(a, b) == is_contained_in_tests[_i].contained);
+ a->destroy(a);
+ b->destroy(b);
+}
+END_TEST
+
+struct {
+ char *net;
+ char *host;
+ bool is_host;
+ bool when_null;
+} is_host_tests[] = {
+ { "0.0.0.0/0", "192.168.1.2", FALSE, FALSE },
+ { "::/0", "fec2::1", FALSE, FALSE },
+ { "192.168.1.2/32", "192.168.1.2", TRUE, TRUE },
+ { "192.168.1.2/32", "192.168.1.1", FALSE, TRUE },
+ { "192.168.1.2/32", "fec2::1", FALSE, TRUE },
+ { "fec2::1/128", "fec2::1", TRUE, TRUE },
+ { "fec2::1/128", "fec2::2", FALSE, TRUE },
+ { "fec2::1/128", "192.168.1.2", FALSE, TRUE },
+};
+
+START_TEST(test_is_host)
+{
+ traffic_selector_t *ts;
+ host_t *h;
+
+ ts = traffic_selector_create_from_cidr(is_host_tests[_i].net, 0, 0, 65535);
+ h = host_create_from_string(is_host_tests[_i].host, 0);
+ ck_assert(ts->is_host(ts, h) == is_host_tests[_i].is_host);
+ ck_assert(ts->is_host(ts, NULL) == is_host_tests[_i].when_null);
+ ts->destroy(ts);
+ h->destroy(h);
+}
+END_TEST
+
+START_TEST(test_is_host_dynamic)
+{
+ traffic_selector_t *ts;
+ host_t *h;
+
+ ts = traffic_selector_create_dynamic(0, 0, 65535);
+ h = host_create_from_string(is_host_tests[_i].host, 0);
+ ck_assert(!ts->is_host(ts, h));
+ ck_assert(ts->is_host(ts, NULL));
+ ts->destroy(ts);
+ h->destroy(h);
+}
+END_TEST
+
+
+struct {
+ char *orig;
+ char *host;
+ char *after;
+} set_address_tests[] = {
+ { "0.0.0.0/0", "192.168.1.2", "0.0.0.0/0" },
+ { "::/0", "fec2::1", "::/0" },
+ { "192.168.1.2/32", "192.168.1.1", "192.168.1.1/32" },
+ { "192.168.1.2/32", "fec2::1", "fec2::1/128" },
+ { "192.168.1.2/32", "%any", "0.0.0.0/0" },
+ { "192.168.1.2/32", "%any6", "::/0" },
+ { "fec2::1/128", "192.168.1.1", "192.168.1.1/32" },
+ { "fec2::1/128", "fec2::2", "fec2::2/128" },
+ { "fec2::1/128", "%any", "0.0.0.0/0" },
+ { "fec2::1/128", "%any6", "::/0" },
+ { NULL, "192.168.1.1", "192.168.1.1/32" },
+ { NULL, "fec2::1", "fec2::1/128" },
+ { NULL, "%any", "0.0.0.0/0" },
+ { NULL, "%any6", "::/0" },
+};
+
+START_TEST(test_set_address)
+{
+ traffic_selector_t *ts;
+ host_t *h;
+
+ if (set_address_tests[_i].orig)
+ {
+ ts = traffic_selector_create_from_cidr(set_address_tests[_i].orig, 0, 0, 65535);
+ ck_assert(!ts->is_dynamic(ts));
+ }
+ else
+ {
+ ts = traffic_selector_create_dynamic(0, 0, 65535);
+ ck_assert(ts->is_dynamic(ts));
+ }
+ h = host_create_from_string(set_address_tests[_i].host, 0);
+ ts->set_address(ts, h);
+ ck_assert(!ts->is_dynamic(ts));
+ verify(set_address_tests[_i].after, NULL, ts);
+ h->destroy(h);
+}
+END_TEST
+
+
+struct {
int res;
struct {
char *net;
@@ -206,6 +569,10 @@ struct {
{ 1, { "2.0.0.0/8", 0, 0, 65535 }, { "1.0.0.0/8", 0, 0, 65535 }, },
{ -1, { "1.0.0.0/8", 0, 0, 65535 }, { "1.0.0.0/16", 0, 0, 65535 }, },
{ 1, { "1.0.0.0/16", 0, 0, 65535 }, { "1.0.0.0/8", 0, 0, 65535 }, },
+ { -1, { "fec1::/64", 0, 0, 65535 }, { "fec2::/64", 0, 0, 65535 }, },
+ { 1, { "fec2::/64", 0, 0, 65535 }, { "fec1::/64", 0, 0, 65535 }, },
+ { -1, { "fec1::/48", 0, 0, 65535 }, { "fec1::/64", 0, 0, 65535 }, },
+ { 1, { "fec1::/64", 0, 0, 65535 }, { "fec1::/48", 0, 0, 65535 }, },
{ -1, { "10.0.0.0/8", 0, 0, 65535 }, { "fec2::/64", 0, 0, 65535 }, },
{ 1, { "fec2::/64", 0, 0, 65535 }, { "10.0.0.0/8", 0, 0, 65535 }, },
@@ -235,12 +602,15 @@ START_TEST(test_cmp)
{
case 0:
ck_assert(traffic_selector_cmp(a, b, NULL) == 0);
+ ck_assert(a->equals(a, b));
break;
case 1:
ck_assert(traffic_selector_cmp(a, b, NULL) > 0);
+ ck_assert(!a->equals(a, b));
break;
case -1:
ck_assert(traffic_selector_cmp(a, b, NULL) < 0);
+ ck_assert(!a->equals(a, b));
break;
}
a->destroy(a);
@@ -248,6 +618,172 @@ START_TEST(test_cmp)
}
END_TEST
+static void verify_clone(traffic_selector_t *ts)
+{
+ traffic_selector_t *clone;
+
+ clone = ts->clone(ts);
+ if (!ts->equals(ts, clone))
+ {
+ fail("%R != %R", ts, clone);
+ }
+ /* equals() already compares most of these but not all */
+ ck_assert(ts->get_type(ts) == clone->get_type(clone));
+ ck_assert(ts->get_protocol(ts) == clone->get_protocol(clone));
+ ck_assert(ts->get_from_port(ts) == clone->get_from_port(clone));
+ ck_assert(ts->get_to_port(ts) == clone->get_to_port(clone));
+ ck_assert_chunk_eq(ts->get_from_address(ts), clone->get_from_address(clone));
+ ck_assert_chunk_eq(ts->get_to_address(ts), clone->get_to_address(clone));
+ ck_assert(ts->is_host(ts, NULL) == clone->is_host(clone, NULL));
+ ck_assert(ts->is_dynamic(ts) == clone->is_dynamic(clone));
+ clone->destroy(clone);
+ ts->destroy(ts);
+}
+
+START_TEST(test_clone)
+{
+ traffic_selector_t *ts;
+ host_t *h;
+
+ ts = traffic_selector_create_dynamic(0, 0, 0);
+ verify_clone(ts);
+ ts = traffic_selector_create_dynamic(IPPROTO_UDP, 123, 456);
+ verify_clone(ts);
+ ts = traffic_selector_create_dynamic(IPPROTO_UDP, 0, 65535);
+ verify_clone(ts);
+
+ h = host_create_from_string("192.168.1.1", 0);
+ ts = traffic_selector_create_dynamic(0, 0, 0);
+ ts->set_address(ts, h);
+ verify_clone(ts);
+ ts = traffic_selector_create_dynamic(IPPROTO_UDP, 123, 456);
+ ts->set_address(ts, h);
+ verify_clone(ts);
+ h->destroy(h);
+
+ ts = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "10.0.0.1", 0, "10.0.0.16", 65535);
+ verify_clone(ts);
+ ts = traffic_selector_create_from_string(IPPROTO_TCP, TS_IPV6_ADDR_RANGE, "fec1::1", 80, "fec1::1:0000", 80);
+ verify_clone(ts);
+ ts = traffic_selector_create_from_cidr("10.0.0.0/8", 0, 0, 65535);
+ verify_clone(ts);
+ ts = traffic_selector_create_from_cidr("fec1::/64", 0, 0, 65535);
+ verify_clone(ts);
+}
+END_TEST
+
+START_TEST(test_hash)
+{
+ traffic_selector_t *a, *b;
+ host_t *h;
+
+ a = traffic_selector_create_dynamic(0, 0, 0);
+ b = traffic_selector_create_from_cidr("0.0.0.0/0", 0, 0, 0);
+ ck_assert(a->hash(a, 0) != a->hash(a, 1));
+ ck_assert_int_eq(a->hash(a, 0), b->hash(b, 0));
+ ck_assert_int_eq(a->hash(a, 1), b->hash(b, 1));
+
+ h = host_create_from_string("192.168.1.1", 0);
+ a->set_address(a, h);
+ ck_assert(a->hash(a, 0) != b->hash(b, 0));
+ h->destroy(h);
+
+ a->destroy(a);
+ a = traffic_selector_create_from_string(0, TS_IPV4_ADDR_RANGE, "192.168.0.0", 0, "192.168.0.255", 65535);
+ ck_assert(a->hash(a, 0) != b->hash(b, 0));
+ b->destroy(b);
+ b = traffic_selector_create_from_cidr("192.168.0.0/24", 0, 0, 65535);
+ ck_assert_int_eq(a->hash(a, 0), b->hash(b, 0));
+ b->destroy(b);
+ b = traffic_selector_create_from_cidr("192.168.0.0/24", IPPROTO_TCP, 0, 65535);
+ ck_assert(a->hash(a, 0) != b->hash(b, 0));
+ b->destroy(b);
+ b = traffic_selector_create_from_cidr("192.168.0.0/24", 0, 123, 456);
+ ck_assert(a->hash(a, 0) != b->hash(b, 0));
+ b->destroy(b);
+ a->destroy(a);
+}
+END_TEST
+
+struct {
+ u_int8_t proto;
+ u_int16_t from_port;
+ u_int16_t to_port;
+ u_int8_t from_type;
+ u_int8_t from_code;
+ u_int8_t to_type;
+ u_int8_t to_code;
+ char *str;
+ char *str_alt;
+} icmp_tests[] = {
+ { IPPROTO_ICMP, 0, 0, 0, 0, 0, 0, "dynamic[icmp/0]", "dynamic[1/0]" },
+ { IPPROTO_ICMP, 3, 3, 3, 0, 3, 0, "dynamic[icmp/3]", "dynamic[1/3]" },
+ { IPPROTO_ICMP, 0x0307, 0x0307, 3, 7, 3, 7, "dynamic[icmp/3(7)]", "dynamic[1/3(7)]" },
+ { IPPROTO_ICMP, 0x0300, 0x040f, 3, 0, 4, 15, "dynamic[icmp/3-4(15)]", "dynamic[1/3-4(15)]" },
+ { IPPROTO_ICMP, 0x0301, 0x040f, 3, 1, 4, 15, "dynamic[icmp/3(1)-4(15)]", "dynamic[1/3(1)-4(15)]" },
+ { IPPROTO_ICMPV6, 0, 0, 0, 0, 0, 0, "dynamic[ipv6-icmp/0]", "dynamic[58/0]" },
+ { IPPROTO_ICMPV6, 1, 1, 1, 0, 1, 0, "dynamic[ipv6-icmp/1]", "dynamic[58/1]" },
+ { IPPROTO_ICMPV6, 0x0104, 0x0104, 1, 4, 1, 4, "dynamic[ipv6-icmp/1(4)]", "dynamic[58/1(4)]" },
+ { IPPROTO_ICMPV6, 0x0100, 0x040f, 1, 0, 4, 15, "dynamic[ipv6-icmp/1-4(15)]", "dynamic[58/1-4(15)]" },
+ { IPPROTO_ICMPV6, 0x0101, 0x040f, 1, 1, 4, 15, "dynamic[ipv6-icmp/1(1)-4(15)]", "dynamic[58/1(1)-4(15)]" },
+};
+
+START_TEST(test_icmp)
+{
+ traffic_selector_t *ts;
+ u_int16_t from, to;
+
+ ts = traffic_selector_create_dynamic(icmp_tests[_i].proto,
+ icmp_tests[_i].from_port, icmp_tests[_i].to_port);
+ from = ts->get_from_port(ts);
+ to = ts->get_to_port(ts);
+ ck_assert_int_eq(icmp_tests[_i].from_type, traffic_selector_icmp_type(from));
+ ck_assert_int_eq(icmp_tests[_i].from_code, traffic_selector_icmp_code(from));
+ ck_assert_int_eq(icmp_tests[_i].to_type, traffic_selector_icmp_type(to));
+ ck_assert_int_eq(icmp_tests[_i].to_code, traffic_selector_icmp_code(to));
+ verify(icmp_tests[_i].str, icmp_tests[_i].str_alt, ts);
+}
+END_TEST
+
+static void verify_list(const char *str, const char *alt, linked_list_t *list)
+{
+ char buf[512];
+
+ snprintf(buf, sizeof(buf), "%#R", list);
+ list->destroy_offset(list, offsetof(traffic_selector_t, destroy));
+ if (!streq(buf, str) && !streq(buf, alt))
+ {
+ fail("%s != %s or %s", buf, str, alt);
+ }
+}
+
+START_TEST(test_printf_hook_null)
+{
+ verify("(null)", NULL, NULL);
+}
+END_TEST
+
+START_TEST(test_printf_hook_hash)
+{
+ linked_list_t *list;
+
+ list = linked_list_create_with_items(
+ traffic_selector_create_from_cidr("10.1.0.0/16", 0, 0, 65535),
+ NULL);
+ verify_list("10.1.0.0/16 ", NULL, list);
+ list = linked_list_create_with_items(
+ traffic_selector_create_from_cidr("10.1.0.0/16", 0, 0, 65535),
+ traffic_selector_create_from_cidr("10.1.0.1/32", IPPROTO_UDP, 1234, 1235),
+ NULL);
+ verify_list("10.1.0.0/16 10.1.0.1/32[udp/1234-1235] ", "10.1.0.0/16 10.1.0.1/32[17/1234-1235] ", list);
+ list = linked_list_create_with_items(
+ traffic_selector_create_from_cidr("10.1.0.0/16", 0, 0, 65535),
+ traffic_selector_create_from_string(IPPROTO_UDP, TS_IPV4_ADDR_RANGE, "10.1.0.1", 1234, "10.1.0.99", 1235),
+ NULL);
+ verify_list("10.1.0.0/16 10.1.0.1..10.1.0.99[udp/1234-1235] ", "10.1.0.0/16 10.1.0.1..10.1.0.99[17/1234-1235] ", list);
+}
+END_TEST
+
Suite *traffic_selector_suite_create()
{
Suite *s;
@@ -260,6 +796,18 @@ Suite *traffic_selector_suite_create()
tcase_add_test(tc, test_create_from_cidr);
tcase_add_test(tc, test_create_from_bytes);
tcase_add_test(tc, test_create_from_subnet);
+ tcase_add_loop_test(tc, test_create_from_rfc3779_format_prefix, 0, countof(rfc3779_prefix_tests));
+ tcase_add_test(tc, test_create_from_rfc3779_format_range);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("addresses");
+ tcase_add_test(tc, test_get_address_range);
+ tcase_add_test(tc, test_get_address_cidr);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("to_subnet");
+ tcase_add_loop_test(tc, test_to_subnet, 0, countof(to_subnet_tests));
+ tcase_add_loop_test(tc, test_to_subnet_port, 0, countof(to_subnet_port_tests));
suite_add_tcase(s, tc);
tc = tcase_create("subset");
@@ -270,15 +818,47 @@ Suite *traffic_selector_suite_create()
tcase_add_test(tc, test_subset_noport);
tcase_add_test(tc, test_subset_noproto);
tcase_add_test(tc, test_subset_nofamily);
+ tcase_add_test(tc, test_subset_dynamic);
+ tcase_add_test(tc, test_subset_opaque);
suite_add_tcase(s, tc);
tc = tcase_create("includes");
tcase_add_loop_test(tc, test_includes, 0, countof(include_tests));
suite_add_tcase(s, tc);
+ tc = tcase_create("is_contained_in");
+ tcase_add_loop_test(tc, test_is_contained_in, 0, countof(is_contained_in_tests));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("is_host");
+ tcase_add_loop_test(tc, test_is_host, 0, countof(is_host_tests));
+ tcase_add_loop_test(tc, test_is_host_dynamic, 0, countof(is_host_tests));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("set_address");
+ tcase_add_loop_test(tc, test_set_address, 0, countof(is_host_tests));
+ suite_add_tcase(s, tc);
+
tc = tcase_create("cmp");
tcase_add_loop_test(tc, test_cmp, 0, countof(cmp_tests));
suite_add_tcase(s, tc);
+ tc = tcase_create("clone");
+ tcase_add_test(tc, test_clone);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("hash");
+ tcase_add_test(tc, test_hash);
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("icmp");
+ tcase_add_loop_test(tc, test_icmp, 0, countof(icmp_tests));
+ suite_add_tcase(s, tc);
+
+ tc = tcase_create("printf hook");
+ tcase_add_test(tc, test_printf_hook_null);
+ tcase_add_test(tc, test_printf_hook_hash);
+ suite_add_tcase(s, tc);
+
return s;
}
diff --git a/src/libstrongswan/tests/test_runner.c b/src/libstrongswan/tests/test_runner.c
index 0bae9c8cd..66d0e612d 100644
--- a/src/libstrongswan/tests/test_runner.c
+++ b/src/libstrongswan/tests/test_runner.c
@@ -265,7 +265,7 @@ static bool pre_test(test_runner_init_t init, char *cfg)
*/
typedef struct {
char *name;
- char msg[512 - sizeof(char*) - 2 * sizeof(int)];
+ char msg[4096 - sizeof(char*) - 2 * sizeof(int)];
const char *file;
int line;
int i;
diff --git a/src/libstrongswan/tests/test_suite.c b/src/libstrongswan/tests/test_suite.c
index 00ac31830..0af34c847 100644
--- a/src/libstrongswan/tests/test_suite.c
+++ b/src/libstrongswan/tests/test_suite.c
@@ -27,7 +27,7 @@
/**
* Failure message buf
*/
-static char failure_buf[512];
+static char failure_buf[4096];
/**
* Source file failure occurred
diff --git a/src/libstrongswan/tests/tests.c b/src/libstrongswan/tests/tests.c
index aed600fbc..0fdfac52d 100644
--- a/src/libstrongswan/tests/tests.c
+++ b/src/libstrongswan/tests/tests.c
@@ -25,8 +25,8 @@
static test_configuration_t tests[] = {
#define TEST_SUITE(x) \
{ .suite = x, },
-#define TEST_SUITE_DEPEND(x, type, args) \
- { .suite = x, .feature = PLUGIN_DEPENDS(type, args) },
+#define TEST_SUITE_DEPEND(x, type, ...) \
+ { .suite = x, .feature = PLUGIN_DEPENDS(type, __VA_ARGS__) },
#include "tests.h"
{ .suite = NULL, }
};
diff --git a/src/libstrongswan/utils/capabilities.c b/src/libstrongswan/utils/capabilities.c
index 923b7d4db..ce5f550b5 100644
--- a/src/libstrongswan/utils/capabilities.c
+++ b/src/libstrongswan/utils/capabilities.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 Tobias Brunner
+ * Copyright (C) 2012-2015 Tobias Brunner
* Hochschule fuer Technik Rapperswil
* Copyright (C) 2012 Martin Willi
* Copyright (C) 2012 revosec AG
@@ -288,13 +288,25 @@ METHOD(capabilities_t, resolve_uid, bool,
#ifdef HAVE_GETPWNAM_R
struct passwd passwd;
- char buf[1024];
+ size_t buflen = 1024;
+ char *buf = NULL;
- err = getpwnam_r(username, &passwd, buf, sizeof(buf), &pwp);
- if (pwp)
+ while (TRUE)
{
- this->uid = pwp->pw_uid;
+ buf = realloc(buf, buflen);
+ err = getpwnam_r(username, &passwd, buf, buflen, &pwp);
+ if (err == ERANGE)
+ {
+ buflen *= 2;
+ continue;
+ }
+ if (pwp)
+ {
+ this->uid = pwp->pw_uid;
+ }
+ break;
}
+ free(buf);
#else /* HAVE GETPWNAM_R */
this->mutex->lock(this->mutex);
pwp = getpwnam(username);
@@ -324,13 +336,25 @@ METHOD(capabilities_t, resolve_gid, bool,
#ifdef HAVE_GETGRNAM_R
struct group group;
- char buf[1024];
+ size_t buflen = 1024;
+ char *buf = NULL;
- err = getgrnam_r(groupname, &group, buf, sizeof(buf), &grp);
- if (grp)
+ while (TRUE)
{
- this->gid = grp->gr_gid;
+ buf = realloc(buf, buflen);
+ err = getgrnam_r(groupname, &group, buf, buflen, &grp);
+ if (err == ERANGE)
+ {
+ buflen *= 2;
+ continue;
+ }
+ if (grp)
+ {
+ this->gid = grp->gr_gid;
+ }
+ break;
}
+ free(buf);
#else /* HAVE_GETGRNAM_R */
this->mutex->lock(this->mutex);
grp = getgrnam(groupname);
@@ -362,12 +386,24 @@ static bool init_supplementary_groups(private_capabilities_t *this)
#ifdef HAVE_GETPWUID_R
struct passwd pwd;
- char buf[1024];
+ size_t buflen = 1024;
+ char *buf = NULL;
- if (getpwuid_r(this->uid, &pwd, buf, sizeof(buf), &pwp) == 0 && pwp)
+ while (TRUE)
{
- res = initgroups(pwp->pw_name, this->gid);
+ buf = realloc(buf, buflen);
+ if (getpwuid_r(this->uid, &pwd, buf, buflen, &pwp) == ERANGE)
+ {
+ buflen *= 2;
+ continue;
+ }
+ if (pwp)
+ {
+ res = initgroups(pwp->pw_name, this->gid);
+ }
+ break;
}
+ free(buf);
#else /* HAVE_GETPWUID_R */
this->mutex->lock(this->mutex);
pwp = getpwuid(this->uid);
diff --git a/src/libstrongswan/utils/identification.c b/src/libstrongswan/utils/identification.c
index b69adf399..da23d143c 100644
--- a/src/libstrongswan/utils/identification.c
+++ b/src/libstrongswan/utils/identification.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2012 Tobias Brunner
+ * Copyright (C) 2009-2015 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -47,10 +47,9 @@ ENUM_BEGIN(id_type_names, ID_ANY, ID_KEY_ID,
"ID_DER_ASN1_DN",
"ID_DER_ASN1_GN",
"ID_KEY_ID");
-ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_USER_ID, ID_KEY_ID,
- "ID_DER_ASN1_GN_URI",
- "ID_USER_ID");
-ENUM_END(id_type_names, ID_USER_ID);
+ENUM_NEXT(id_type_names, ID_DER_ASN1_GN_URI, ID_DER_ASN1_GN_URI, ID_KEY_ID,
+ "ID_DER_ASN1_GN_URI");
+ENUM_END(id_type_names, ID_DER_ASN1_GN_URI);
/**
* coding of X.501 distinguished name
@@ -478,7 +477,7 @@ static status_t atodn(char *src, chunk_t *dn)
name.len -= whitespace;
rdn_type = (x501rdns[i].type == ASN1_PRINTABLESTRING
&& !asn1_is_printablestring(name))
- ? ASN1_T61STRING : x501rdns[i].type;
+ ? ASN1_UTF8STRING : x501rdns[i].type;
if (rdn_count < RDN_MAX)
{
@@ -579,6 +578,19 @@ METHOD(identification_t, contains_wildcards_memchr, bool,
return memchr(this->encoded.ptr, '*', this->encoded.len) != NULL;
}
+METHOD(identification_t, hash_binary, u_int,
+ private_identification_t *this, u_int inc)
+{
+ u_int hash;
+
+ hash = chunk_hash_inc(chunk_from_thing(this->type), inc);
+ if (this->type != ID_ANY)
+ {
+ hash = chunk_hash_inc(this->encoded, hash);
+ }
+ return hash;
+}
+
METHOD(identification_t, equals_binary, bool,
private_identification_t *this, identification_t *other)
{
@@ -687,6 +699,24 @@ METHOD(identification_t, equals_dn, bool,
return compare_dn(this->encoded, other->get_encoding(other), NULL);
}
+METHOD(identification_t, hash_dn, u_int,
+ private_identification_t *this, u_int inc)
+{
+ enumerator_t *rdns;
+ chunk_t oid, data;
+ u_char type;
+ u_int hash;
+
+ hash = chunk_hash_inc(chunk_from_thing(this->type), inc);
+ rdns = create_rdn_enumerator(this->encoded);
+ while (rdns->enumerate(rdns, &oid, &type, &data))
+ {
+ hash = chunk_hash_inc(data, chunk_hash_inc(oid, hash));
+ }
+ rdns->destroy(rdns);
+ return hash;
+}
+
METHOD(identification_t, equals_strcasecmp, bool,
private_identification_t *this, identification_t *other)
{
@@ -828,7 +858,6 @@ int identification_printf_hook(printf_hook_data_t *data,
case ID_FQDN:
case ID_RFC822_ADDR:
case ID_DER_ASN1_GN_URI:
- case ID_USER_ID:
chunk_printable(this->encoded, &proper, '?');
snprintf(buf, sizeof(buf), "%.*s", (int)proper.len, proper.ptr);
chunk_free(&proper);
@@ -903,23 +932,26 @@ static private_identification_t *identification_create(id_type_t type)
switch (type)
{
case ID_ANY:
+ this->public.hash = _hash_binary;
this->public.matches = _matches_any;
this->public.equals = _equals_binary;
this->public.contains_wildcards = return_true;
break;
case ID_FQDN:
case ID_RFC822_ADDR:
- case ID_USER_ID:
+ this->public.hash = _hash_binary;
this->public.matches = _matches_string;
this->public.equals = _equals_strcasecmp;
this->public.contains_wildcards = _contains_wildcards_memchr;
break;
case ID_DER_ASN1_DN:
+ this->public.hash = _hash_dn;
this->public.equals = _equals_dn;
this->public.matches = _matches_dn;
this->public.contains_wildcards = _contains_wildcards_dn;
break;
default:
+ this->public.hash = _hash_binary;
this->public.equals = _equals_binary;
this->public.matches = _matches_binary;
this->public.contains_wildcards = return_false;
diff --git a/src/libstrongswan/utils/identification.h b/src/libstrongswan/utils/identification.h
index e6a9fe1c6..5f27ba112 100644
--- a/src/libstrongswan/utils/identification.h
+++ b/src/libstrongswan/utils/identification.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Tobias Brunner
+ * Copyright (C) 2009-2015 Tobias Brunner
* Copyright (C) 2005-2009 Martin Willi
* Copyright (C) 2005 Jan Hutter
* Hochschule fuer Technik Rapperswil
@@ -129,11 +129,6 @@ enum id_type_t {
* Private ID type which represents a GeneralName of type URI
*/
ID_DER_ASN1_GN_URI = 201,
-
- /**
- * Private ID type which represents a user ID
- */
- ID_USER_ID = 202
};
/**
@@ -219,6 +214,14 @@ struct identification_t {
id_type_t (*get_type) (identification_t *this);
/**
+ * Create a hash value for this identification_t object.
+ *
+ * @param inc optional value for incremental hashing
+ * @return hash value
+ */
+ u_int (*hash) (identification_t *this, u_int inc);
+
+ /**
* Check if two identification_t objects are equal.
*
* @param other other identification_t object
diff --git a/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c
index 466c673d9..af5494052 100644
--- a/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c
+++ b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.c
@@ -843,7 +843,8 @@ int builtin_vsnprintf(char *buffer, size_t n, const char *format, va_list ap)
/* String */
sarg = va_arg(ap, const char *);
sarg = sarg ? sarg : "(null)";
- slen = strlen(sarg);
+ slen = prec != -1 ? strnlen(sarg, prec)
+ : strlen(sarg);
goto is_string;
}
case 'm':
diff --git a/src/libstrongswan/utils/printf_hook/printf_hook_builtin.h b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.h
index 409b5bf3d..efbacff6f 100644
--- a/src/libstrongswan/utils/printf_hook/printf_hook_builtin.h
+++ b/src/libstrongswan/utils/printf_hook/printf_hook_builtin.h
@@ -15,7 +15,7 @@
/**
* @defgroup printf_hook_builtin printf_hook_builtin
- * @{ @ingroup utils
+ * @{ @ingroup printf_hook
*/
#ifndef PRINTF_HOOK_BUILTIN_H_
diff --git a/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h b/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h
index 2f9ee5983..7c24b05e2 100644
--- a/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h
+++ b/src/libstrongswan/utils/printf_hook/printf_hook_vstr.h
@@ -16,7 +16,7 @@
/**
* @defgroup printf_hook_vstr printf_hook_vstr
- * @{ @ingroup utils
+ * @{ @ingroup printf_hook
*/
#ifndef PRINTF_HOOK_VSTR_H_
diff --git a/src/libstrongswan/utils/utils.c b/src/libstrongswan/utils/utils.c
index 9b516accd..b4a4db802 100644
--- a/src/libstrongswan/utils/utils.c
+++ b/src/libstrongswan/utils/utils.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008-2014 Tobias Brunner
+ * Copyright (C) 2008-2015 Tobias Brunner
* Copyright (C) 2005-2008 Martin Willi
* Hochschule fuer Technik Rapperswil
*
@@ -16,15 +16,38 @@
#include "utils.h"
+#include <sys/types.h>
#include <unistd.h>
#include <limits.h>
+#include <ctype.h>
#ifndef WIN32
# include <signal.h>
#endif
+#ifndef HAVE_CLOSEFROM
+#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
+# include <sys/stat.h>
+# include <fcntl.h>
+# include <sys/syscall.h>
+/* This is from the kernel sources. We limit the length of directory names to
+ * 256 as we only use it to enumerate FDs. */
+struct linux_dirent64 {
+ u_int64_t d_ino;
+ int64_t d_off;
+ unsigned short d_reclen;
+ unsigned char d_type;
+ char d_name[256];
+};
+#else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */
+# include <dirent.h>
+#endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */
+#endif
+
#include <library.h>
#include <collections/enumerator.h>
+#define FD_DIR "/proc/self/fd"
+
#ifdef WIN32
#include <threading/mutex.h>
@@ -110,43 +133,89 @@ void wait_sigint()
/**
* Described in header.
*/
-void closefrom(int lowfd)
+void closefrom(int low_fd)
{
- char fd_dir[PATH_MAX];
- int maxfd, fd, len;
+ int max_fd, dir_fd, fd;
/* try to close only open file descriptors on Linux... */
- len = snprintf(fd_dir, sizeof(fd_dir), "/proc/%u/fd", getpid());
- if (len > 0 && len < sizeof(fd_dir) && access(fd_dir, F_OK) == 0)
+#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
+ /* By directly using a syscall we avoid any calls that might be unsafe after
+ * fork() (e.g. malloc()). */
+ char buffer[sizeof(struct linux_dirent64)];
+ struct linux_dirent64 *entry;
+ int offset, len;
+
+ dir_fd = open("/proc/self/fd", O_RDONLY);
+ if (dir_fd != -1)
{
- enumerator_t *enumerator = enumerator_create_directory(fd_dir);
- if (enumerator)
+ while ((len = syscall(SYS_getdents64, dir_fd, buffer,
+ sizeof(buffer))) > 0)
{
- char *rel;
- while (enumerator->enumerate(enumerator, &rel, NULL, NULL))
+ for (offset = 0; offset < len; offset += entry->d_reclen)
{
- fd = atoi(rel);
- if (fd >= lowfd)
+ entry = (struct linux_dirent64*)(buffer + offset);
+ if (!isdigit(entry->d_name[0]))
+ {
+ continue;
+ }
+ fd = atoi(entry->d_name);
+ if (fd != dir_fd && fd >= low_fd)
{
close(fd);
}
}
- enumerator->destroy(enumerator);
- return;
}
+ close(dir_fd);
+ return;
+ }
+#else /* !defined(__linux__) || !defined(HAVE_SYS_SYSCALL_H) */
+ /* This is potentially unsafe when called after fork() in multi-threaded
+ * applications. In particular opendir() will require an allocation.
+ * Depends on how the malloc() implementation handles such situations. */
+ DIR *dir;
+ struct dirent *entry;
+
+#ifndef HAVE_DIRFD
+ /* if we don't have dirfd() lets close the lowest FD and hope it gets reused
+ * by opendir() */
+ close(low_fd);
+ dir_fd = low_fd++;
+#endif
+
+ dir = opendir(FD_DIR);
+ if (dir)
+ {
+#ifdef HAVE_DIRFD
+ dir_fd = dirfd(dir);
+#endif
+ while ((entry = readdir(dir)))
+ {
+ if (!isdigit(entry->d_name[0]))
+ {
+ continue;
+ }
+ fd = atoi(entry->d_name);
+ if (fd != dir_fd && fd >= low_fd)
+ {
+ close(fd);
+ }
+ }
+ closedir(dir);
+ return;
}
+#endif /* defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) */
/* ...fall back to closing all fds otherwise */
#ifdef WIN32
- maxfd = _getmaxstdio();
+ max_fd = _getmaxstdio();
#else
- maxfd = (int)sysconf(_SC_OPEN_MAX);
+ max_fd = (int)sysconf(_SC_OPEN_MAX);
#endif
- if (maxfd < 0)
+ if (max_fd < 0)
{
- maxfd = 256;
+ max_fd = 256;
}
- for (fd = lowfd; fd < maxfd; fd++)
+ for (fd = low_fd; fd < max_fd; fd++)
{
close(fd);
}
diff --git a/src/libstrongswan/utils/utils/string.c b/src/libstrongswan/utils/utils/string.c
index 14087e765..56910ed79 100644
--- a/src/libstrongswan/utils/utils/string.c
+++ b/src/libstrongswan/utils/utils/string.c
@@ -44,7 +44,7 @@ char* translate(char *str, const char *from, const char *to)
char* strreplace(const char *str, const char *search, const char *replace)
{
size_t len, slen, rlen, count = 0;
- char *res, *pos, *found, *dst;
+ char *res, *pos, *found = NULL, *dst;
if (!str || !*str || !search || !*search || !replace)
{
diff --git a/src/libtls/tests/tls_tests.c b/src/libtls/tests/tls_tests.c
index 2c2c5bacc..3f22f9c82 100644
--- a/src/libtls/tests/tls_tests.c
+++ b/src/libtls/tests/tls_tests.c
@@ -25,8 +25,8 @@
static test_configuration_t tests[] = {
#define TEST_SUITE(x) \
{ .suite = x, },
-#define TEST_SUITE_DEPEND(x, type, args) \
- { .suite = x, .feature = PLUGIN_DEPENDS(type, args) },
+#define TEST_SUITE_DEPEND(x, type, ...) \
+ { .suite = x, .feature = PLUGIN_DEPENDS(type, __VA_ARGS__) },
#include "tls_tests.h"
{ .suite = NULL, }
};
diff --git a/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c
index 30e505246..67c33ee63 100644
--- a/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c
+++ b/src/libtnccs/plugins/tnc_tnccs/tnc_tnccs_manager.c
@@ -729,7 +729,9 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result,
list = linked_list_create();
tnccs = entry->tnccs;
- peer_id = tnccs->tls.get_peer_id(&tnccs->tls);
+ peer_id = tnccs->tls.is_server(&tnccs->tls) ?
+ tnccs->tls.get_peer_id(&tnccs->tls) :
+ tnccs->tls.get_server_id(&tnccs->tls);
if (peer_id)
{
switch (peer_id->get_type(peer_id))
@@ -771,7 +773,9 @@ METHOD(tnccs_manager_t, get_attribute, TNC_Result,
}
}
- peer_ip = tnccs->get_peer_ip(tnccs);
+ peer_ip = tnccs->tls.is_server(&tnccs->tls) ?
+ tnccs->get_peer_ip(tnccs) :
+ tnccs->get_server_ip(tnccs);
if (peer_ip)
{
switch (peer_ip->get_family(peer_ip))
diff --git a/src/libtncif/tncif_pa_subtypes.c b/src/libtncif/tncif_pa_subtypes.c
index bf1e999b3..d83c3255d 100644
--- a/src/libtncif/tncif_pa_subtypes.c
+++ b/src/libtncif/tncif_pa_subtypes.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2011 Andreas Steffen
+ * Copyright (C) 2010-2015 Andreas Steffen
*
* HSR Hochschule fuer Technik Rapperswil
*
@@ -16,6 +16,7 @@
#include "tncif_pa_subtypes.h"
+/* IETF PA Subtype names */
ENUM_BEGIN(pa_subtype_ietf_names, PA_SUBTYPE_IETF_TESTING, PA_SUBTYPE_IETF_NEA_CLIENT,
"Testing",
"Operating System",
@@ -33,6 +34,7 @@ ENUM_NEXT(pa_subtype_ietf_names, PA_SUBTYPE_IETF_ANY, PA_SUBTYPE_IETF_ANY,
);
ENUM_END(pa_subtype_ietf_names, PA_SUBTYPE_IETF_ANY);
+/* TCG PA Subtype names */
ENUM_BEGIN(pa_subtype_tcg_names, PA_SUBTYPE_TCG_PTS, PA_SUBTYPE_TCG_SWID,
"PTS",
"SCAP",
@@ -44,6 +46,56 @@ ENUM_NEXT(pa_subtype_tcg_names, PA_SUBTYPE_TCG_ANY, PA_SUBTYPE_TCG_ANY,
);
ENUM_END(pa_subtype_tcg_names, PA_SUBTYPE_TCG_ANY);
+/* PWG PA Subtype names */
+ENUM_BEGIN(pa_subtype_pwg_names, PA_SUBTYPE_PWG_HCD_TESTING,
+ PA_SUBTYPE_PWG_HCD_UNKNOWN,
+ "HCD Testing",
+ "HCD Other",
+ "HCD Unknown"
+);
+ENUM_NEXT(pa_subtype_pwg_names, PA_SUBTYPE_PWG_HCD_CONSOLE,
+ PA_SUBTYPE_PWG_HCD_COVER,
+ PA_SUBTYPE_PWG_HCD_UNKNOWN,
+ "HCD Console",
+ "HCD System",
+ "HCD Cover"
+);
+ENUM_NEXT(pa_subtype_pwg_names, PA_SUBTYPE_PWG_HCD_INPUT_TRAY,
+ PA_SUBTYPE_PWG_HCD_MARKER,
+ PA_SUBTYPE_PWG_HCD_COVER,
+ "HCD Input Tray",
+ "HCD Output Tray",
+ "HCD Marker"
+);
+ENUM_NEXT(pa_subtype_pwg_names, PA_SUBTYPE_PWG_HCD_MEDIA_PATH,
+ PA_SUBTYPE_PWG_HCD_INTERPRETER,
+ PA_SUBTYPE_PWG_HCD_MARKER,
+ "HCD Media Path",
+ "HCD Channel",
+ "HCD Interpreter"
+);
+ENUM_NEXT(pa_subtype_pwg_names, PA_SUBTYPE_PWG_HCD_FINISHER,
+ PA_SUBTYPE_PWG_HCD_FINISHER,
+ PA_SUBTYPE_PWG_HCD_INTERPRETER,
+ "HCD Finisher"
+);
+ENUM_NEXT(pa_subtype_pwg_names, PA_SUBTYPE_PWG_HCD_INTERFACE,
+ PA_SUBTYPE_PWG_HCD_INTERFACE,
+ PA_SUBTYPE_PWG_HCD_FINISHER,
+ "HCD Interface"
+);
+ENUM_NEXT(pa_subtype_pwg_names, PA_SUBTYPE_PWG_HCD_SCANNER,
+ PA_SUBTYPE_PWG_HCD_SCANNER,
+ PA_SUBTYPE_PWG_HCD_INTERFACE,
+ "HCD Scanner"
+);
+ENUM_NEXT(pa_subtype_pwg_names, PA_SUBTYPE_PWG_ANY, PA_SUBTYPE_PWG_ANY,
+ PA_SUBTYPE_PWG_HCD_SCANNER,
+ "ANY"
+);
+ENUM_END(pa_subtype_pwg_names, PA_SUBTYPE_PWG_ANY);
+
+/* FHH PA Subtype names */
ENUM_BEGIN(pa_subtype_fhh_names, PA_SUBTYPE_FHH_HOSTSCANNER, PA_SUBTYPE_FHH_DUMMY,
"HostScanner",
"Dummy"
@@ -63,6 +115,7 @@ ENUM_NEXT(pa_subtype_fhh_names, PA_SUBTYPE_FHH_ANY, PA_SUBTYPE_FHH_ANY,
);
ENUM_END(pa_subtype_fhh_names, PA_SUBTYPE_FHH_ANY);
+/* ITA-HSR PA Subtype names */
ENUM_BEGIN(pa_subtype_ita_names, PA_SUBTYPE_ITA_TEST, PA_SUBTYPE_ITA_ECHO,
"Test",
"Echo"
@@ -84,6 +137,8 @@ enum_name_t* get_pa_subtype_names(pen_t pen)
return pa_subtype_ietf_names;
case PEN_TCG:
return pa_subtype_tcg_names;
+ case PEN_PWG:
+ return pa_subtype_pwg_names;
case PEN_FHH:
return pa_subtype_fhh_names;
case PEN_ITA:
diff --git a/src/libtncif/tncif_pa_subtypes.h b/src/libtncif/tncif_pa_subtypes.h
index 0855d1df3..d6dcad025 100644
--- a/src/libtncif/tncif_pa_subtypes.h
+++ b/src/libtncif/tncif_pa_subtypes.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2011 Andreas Steffen, HSR Hochschule fuer Technik Rapperswil
+ * Copyright (C) 2011-2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -22,6 +23,7 @@
typedef enum pa_subtype_ietf_t pa_subtype_ietf_t;
typedef enum pa_subtype_tcg_t pa_subtype_tcg_t;
+typedef enum pa_subtype_pwg_t pa_subtype_pwg_t;
typedef enum pa_subtype_fhh_t pa_subtype_fhh_t;
typedef enum pa_subtype_ita_t pa_subtype_ita_t;
@@ -65,6 +67,33 @@ extern enum_name_t *pa_subtype_ietf_names;
extern enum_name_t *pa_subtype_tcg_names;
/**
+ * PA-TNC PWG Subtypes
+ */
+ enum pa_subtype_pwg_t {
+ PA_SUBTYPE_PWG_HCD_TESTING = 0x00,
+ PA_SUBTYPE_PWG_HCD_OTHER = 0x01,
+ PA_SUBTYPE_PWG_HCD_UNKNOWN = 0x02,
+ PA_SUBTYPE_PWG_HCD_CONSOLE = 0x04,
+ PA_SUBTYPE_PWG_HCD_SYSTEM = 0x05,
+ PA_SUBTYPE_PWG_HCD_COVER = 0x06,
+ PA_SUBTYPE_PWG_HCD_INPUT_TRAY = 0x08,
+ PA_SUBTYPE_PWG_HCD_OUTPUT_TRAY = 0x09,
+ PA_SUBTYPE_PWG_HCD_MARKER = 0x0a,
+ PA_SUBTYPE_PWG_HCD_MEDIA_PATH = 0x0d,
+ PA_SUBTYPE_PWG_HCD_CHANNEL = 0x0e,
+ PA_SUBTYPE_PWG_HCD_INTERPRETER = 0x0f,
+ PA_SUBTYPE_PWG_HCD_FINISHER = 0x1e,
+ PA_SUBTYPE_PWG_HCD_INTERFACE = 0x28,
+ PA_SUBTYPE_PWG_HCD_SCANNER = 0x32,
+ PA_SUBTYPE_PWG_ANY = 0xff
+};
+
+/**
+ * enum name for pa_subtype_pwg_t.
+ */
+extern enum_name_t *pa_subtype_pwg_names;
+
+/**
* PA-TNC FHH Subtypes
*/
enum pa_subtype_fhh_t {
diff --git a/src/pki/Makefile.am b/src/pki/Makefile.am
index ab407e021..a3da0ab04 100644
--- a/src/pki/Makefile.am
+++ b/src/pki/Makefile.am
@@ -3,17 +3,18 @@ SUBDIRS = man
bin_PROGRAMS = pki
pki_SOURCES = pki.c pki.h command.c command.h \
+ commands/acert.c \
+ commands/dn.c \
commands/gen.c \
commands/issue.c \
commands/keyid.c \
+ commands/pkcs12.c \
+ commands/pkcs7.c \
+ commands/print.c \
commands/pub.c \
commands/req.c \
commands/self.c \
- commands/print.c \
commands/signcrl.c \
- commands/acert.c \
- commands/pkcs7.c \
- commands/pkcs12.c \
commands/verify.c
pki_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
diff --git a/src/pki/Makefile.in b/src/pki/Makefile.in
index 4205469fc..b4829f777 100644
--- a/src/pki/Makefile.in
+++ b/src/pki/Makefile.in
@@ -103,12 +103,13 @@ am__installdirs = "$(DESTDIR)$(bindir)"
PROGRAMS = $(bin_PROGRAMS)
am__dirstamp = $(am__leading_dot)dirstamp
am_pki_OBJECTS = pki.$(OBJEXT) command.$(OBJEXT) \
+ commands/acert.$(OBJEXT) commands/dn.$(OBJEXT) \
commands/gen.$(OBJEXT) commands/issue.$(OBJEXT) \
- commands/keyid.$(OBJEXT) commands/pub.$(OBJEXT) \
- commands/req.$(OBJEXT) commands/self.$(OBJEXT) \
- commands/print.$(OBJEXT) commands/signcrl.$(OBJEXT) \
- commands/acert.$(OBJEXT) commands/pkcs7.$(OBJEXT) \
- commands/pkcs12.$(OBJEXT) commands/verify.$(OBJEXT)
+ commands/keyid.$(OBJEXT) commands/pkcs12.$(OBJEXT) \
+ commands/pkcs7.$(OBJEXT) commands/print.$(OBJEXT) \
+ commands/pub.$(OBJEXT) commands/req.$(OBJEXT) \
+ commands/self.$(OBJEXT) commands/signcrl.$(OBJEXT) \
+ commands/verify.$(OBJEXT)
pki_OBJECTS = $(am_pki_OBJECTS)
pki_DEPENDENCIES = $(top_builddir)/src/libstrongswan/libstrongswan.la
AM_V_lt = $(am__v_lt_@AM_V@)
@@ -445,17 +446,18 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
SUBDIRS = man
pki_SOURCES = pki.c pki.h command.c command.h \
+ commands/acert.c \
+ commands/dn.c \
commands/gen.c \
commands/issue.c \
commands/keyid.c \
+ commands/pkcs12.c \
+ commands/pkcs7.c \
+ commands/print.c \
commands/pub.c \
commands/req.c \
commands/self.c \
- commands/print.c \
commands/signcrl.c \
- commands/acert.c \
- commands/pkcs7.c \
- commands/pkcs12.c \
commands/verify.c
pki_LDADD = $(top_builddir)/src/libstrongswan/libstrongswan.la
@@ -552,27 +554,29 @@ commands/$(am__dirstamp):
commands/$(DEPDIR)/$(am__dirstamp):
@$(MKDIR_P) commands/$(DEPDIR)
@: > commands/$(DEPDIR)/$(am__dirstamp)
+commands/acert.$(OBJEXT): commands/$(am__dirstamp) \
+ commands/$(DEPDIR)/$(am__dirstamp)
+commands/dn.$(OBJEXT): commands/$(am__dirstamp) \
+ commands/$(DEPDIR)/$(am__dirstamp)
commands/gen.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
commands/issue.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
commands/keyid.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
-commands/pub.$(OBJEXT): commands/$(am__dirstamp) \
- commands/$(DEPDIR)/$(am__dirstamp)
-commands/req.$(OBJEXT): commands/$(am__dirstamp) \
+commands/pkcs12.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
-commands/self.$(OBJEXT): commands/$(am__dirstamp) \
+commands/pkcs7.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
commands/print.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
-commands/signcrl.$(OBJEXT): commands/$(am__dirstamp) \
+commands/pub.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
-commands/acert.$(OBJEXT): commands/$(am__dirstamp) \
+commands/req.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
-commands/pkcs7.$(OBJEXT): commands/$(am__dirstamp) \
+commands/self.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
-commands/pkcs12.$(OBJEXT): commands/$(am__dirstamp) \
+commands/signcrl.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
commands/verify.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
@@ -591,6 +595,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/command.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pki.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/acert.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/dn.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/gen.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/issue.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/keyid.Po@am__quote@
diff --git a/src/pki/command.h b/src/pki/command.h
index d49adda09..e55c579e4 100644
--- a/src/pki/command.h
+++ b/src/pki/command.h
@@ -24,7 +24,7 @@
/**
* Maximum number of commands (+1).
*/
-#define MAX_COMMANDS 13
+#define MAX_COMMANDS 14
/**
* Maximum number of options in a command (+3)
diff --git a/src/pki/commands/dn.c b/src/pki/commands/dn.c
new file mode 100644
index 000000000..75585fc16
--- /dev/null
+++ b/src/pki/commands/dn.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2015 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "pki.h"
+
+#include <credentials/certificates/certificate.h>
+
+#include <errno.h>
+
+/**
+ * Extract subject DN
+ */
+static int dn()
+{
+ identification_t *id;
+ certificate_t *cert;
+ chunk_t chunk;
+ enum {
+ FORMAT_CONFIG,
+ FORMAT_HEX,
+ FORMAT_BASE64,
+ FORMAT_BINARY,
+ } format = FORMAT_CONFIG;
+ char *arg, *file = NULL, *fmt;
+
+ while (TRUE)
+ {
+ switch (command_getopt(&arg))
+ {
+ case 'h':
+ return command_usage(NULL);
+ case 'f':
+ if (streq(arg, "hex"))
+ {
+ format = FORMAT_HEX;
+ }
+ else if (streq(arg, "base64"))
+ {
+ format = FORMAT_BASE64;
+ }
+ else if (streq(arg, "bin"))
+ {
+ format = FORMAT_BINARY;
+ }
+ else if (!streq(arg, "config"))
+ {
+ return command_usage( "invalid output format");
+ }
+ continue;
+ case 'i':
+ file = arg;
+ continue;
+ case EOF:
+ break;
+ default:
+ return command_usage("invalid --print option");
+ }
+ break;
+ }
+ if (file)
+ {
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_FROM_FILE, file, BUILD_END);
+ }
+ else
+ {
+ chunk_t chunk;
+
+ set_file_mode(stdin, CERT_ASN1_DER);
+ if (!chunk_from_fd(0, &chunk))
+ {
+ fprintf(stderr, "reading input failed: %s\n", strerror(errno));
+ return 1;
+ }
+ cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB, chunk, BUILD_END);
+ free(chunk.ptr);
+ }
+ if (!cert)
+ {
+ fprintf(stderr, "parsing input failed\n");
+ return 1;
+ }
+ id = cert->get_subject(cert);
+ if (!id)
+ {
+ fprintf(stderr, "failed to get certificate's subject DN\n");
+ cert->destroy(cert);
+ return 1;
+ }
+ fmt = "%.*s\n";
+ switch (format)
+ {
+ case FORMAT_CONFIG:
+ fmt = "\"asn1dn:#%.*s\"\n";
+ /* fall-through */
+ case FORMAT_HEX:
+ chunk = chunk_to_hex(id->get_encoding(id), NULL, FALSE);
+ printf(fmt, (int)chunk.len, chunk.ptr);
+ chunk_free(&chunk);
+ break;
+ case FORMAT_BASE64:
+ chunk = chunk_to_base64(id->get_encoding(id), NULL);
+ printf(fmt, (int)chunk.len, chunk.ptr);
+ chunk_free(&chunk);
+ break;
+ case FORMAT_BINARY:
+ chunk = id->get_encoding(id);
+ if (fwrite(chunk.ptr, chunk.len, 1, stdout) != 1)
+ {
+ fprintf(stderr, "writing subject DN failed\n");
+ }
+ break;
+ }
+ cert->destroy(cert);
+ return 0;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+ command_register((command_t)
+ { dn, 'd', "dn",
+ "extract the subject DN of an X.509 certificate",
+ {"[--in file] [--format config|hex|base64|bin]"},
+ {
+ {"help", 'h', 0, "show usage information"},
+ {"in", 'i', 1, "input file, default: stdin"},
+ {"format", 'f', 1, "output format, default: config"},
+ }
+ });
+}
diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c
index 6a2d09d78..2dc9fcce3 100644
--- a/src/pki/commands/issue.c
+++ b/src/pki/commands/issue.c
@@ -64,6 +64,8 @@ static int issue()
certificate_t *cert_req = NULL, *cert = NULL, *ca =NULL;
private_key_t *private = NULL;
public_key_t *public = NULL;
+ credential_type_t type = CRED_PUBLIC_KEY;
+ key_type_t subtype = KEY_ANY;
bool pkcs10 = FALSE;
char *file = NULL, *dn = NULL, *hex = NULL, *cacert = NULL, *cakey = NULL;
char *error = NULL, *keyid = NULL;
@@ -100,6 +102,21 @@ static int issue()
{
pkcs10 = TRUE;
}
+ else if (streq(arg, "rsa"))
+ {
+ type = CRED_PRIVATE_KEY;
+ subtype = KEY_RSA;
+ }
+ else if (streq(arg, "ecdsa"))
+ {
+ type = CRED_PRIVATE_KEY;
+ subtype = KEY_ECDSA;
+ }
+ else if (streq(arg, "bliss"))
+ {
+ type = CRED_PRIVATE_KEY;
+ subtype = KEY_BLISS;
+ }
else if (!streq(arg, "pub"))
{
error = "invalid input type";
@@ -447,10 +464,10 @@ static int issue()
}
else
{
- DBG2(DBG_LIB, "Reading public key:");
+ DBG2(DBG_LIB, "Reading key:");
if (file)
{
- public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
+ public = lib->creds->create(lib->creds, type, subtype,
BUILD_FROM_FILE, file, BUILD_END);
}
else
@@ -460,13 +477,19 @@ static int issue()
if (!chunk_from_fd(0, &chunk))
{
fprintf(stderr, "%s: ", strerror(errno));
- error = "reading public key failed";
+ error = "reading key failed";
goto end;
}
- public = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY,
+ public = lib->creds->create(lib->creds, type, subtype,
BUILD_BLOB, chunk, BUILD_END);
free(chunk.ptr);
}
+ if (public && type == CRED_PRIVATE_KEY)
+ {
+ private_key_t *priv = (private_key_t*)public;
+ public = priv->get_public_key(priv);
+ priv->destroy(priv);
+ }
}
if (!public)
{
@@ -557,7 +580,7 @@ static void __attribute__ ((constructor))reg()
command_register((command_t) {
issue, 'i', "issue",
"issue a certificate using a CA certificate and key",
- {"[--in file] [--type pub|pkcs10] --cakey file|--cakeyid hex",
+ {"[--in file] [--type pub|pkcs10|rsa|ecdsa|bliss] --cakey file|--cakeyid hex",
" --cacert file [--dn subject-dn] [--san subjectAltName]+",
"[--lifetime days] [--serial hex] [--ca] [--pathlen len]",
"[--flag serverAuth|clientAuth|crlSign|ocspSigning|msSmartcardLogon]+",
@@ -568,7 +591,7 @@ static void __attribute__ ((constructor))reg()
"[--digest md5|sha1|sha224|sha256|sha384|sha512] [--outform der|pem]"},
{
{"help", 'h', 0, "show usage information"},
- {"in", 'i', 1, "public key/request file to issue, default: stdin"},
+ {"in", 'i', 1, "key/request file to issue, default: stdin"},
{"type", 't', 1, "type of input, default: pub"},
{"cacert", 'c', 1, "CA certificate file"},
{"cakey", 'k', 1, "CA private key file"},
diff --git a/src/pki/man/Makefile.am b/src/pki/man/Makefile.am
index 4c901ae3c..fc9440031 100644
--- a/src/pki/man/Makefile.am
+++ b/src/pki/man/Makefile.am
@@ -1,15 +1,16 @@
man1_MANS = \
pki.1 \
+ pki---acert.1 \
+ pki---dn.1 \
pki---gen.1 \
- pki---self.1 \
pki---issue.1 \
- pki---signcrl.1 \
- pki---acert.1 \
- pki---req.1 \
- pki---pkcs7.1 \
pki---keyid.1 \
+ pki---pkcs7.1 \
pki---print.1 \
pki---pub.1 \
+ pki---req.1 \
+ pki---self.1 \
+ pki---signcrl.1 \
pki---verify.1
CLEANFILES = $(man1_MANS)
diff --git a/src/pki/man/Makefile.in b/src/pki/man/Makefile.in
index 45355bacd..62942d108 100644
--- a/src/pki/man/Makefile.in
+++ b/src/pki/man/Makefile.in
@@ -79,13 +79,13 @@ build_triplet = @build@
host_triplet = @host@
subdir = src/pki/man
DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \
- $(srcdir)/pki.1.in $(srcdir)/pki---gen.1.in \
+ $(srcdir)/pki.1.in $(srcdir)/pki---acert.1.in \
+ $(srcdir)/pki---dn.1.in $(srcdir)/pki---gen.1.in \
$(srcdir)/pki---issue.1.in $(srcdir)/pki---keyid.1.in \
- $(srcdir)/pki---pkcs7.1.in $(srcdir)/pki---pkcs12.1.in \
+ $(srcdir)/pki---pkcs12.1.in $(srcdir)/pki---pkcs7.1.in \
$(srcdir)/pki---print.1.in $(srcdir)/pki---pub.1.in \
$(srcdir)/pki---req.1.in $(srcdir)/pki---self.1.in \
- $(srcdir)/pki---signcrl.1.in $(srcdir)/pki---acert.1.in \
- $(srcdir)/pki---verify.1.in
+ $(srcdir)/pki---signcrl.1.in $(srcdir)/pki---verify.1.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/config/libtool.m4 \
$(top_srcdir)/m4/config/ltoptions.m4 \
@@ -101,10 +101,10 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_HEADER = $(top_builddir)/config.h
-CONFIG_CLEAN_FILES = pki.1 pki---gen.1 pki---issue.1 pki---keyid.1 \
- pki---pkcs7.1 pki---pkcs12.1 pki---print.1 pki---pub.1 \
- pki---req.1 pki---self.1 pki---signcrl.1 pki---acert.1 \
- pki---verify.1
+CONFIG_CLEAN_FILES = pki.1 pki---acert.1 pki---dn.1 pki---gen.1 \
+ pki---issue.1 pki---keyid.1 pki---pkcs12.1 pki---pkcs7.1 \
+ pki---print.1 pki---pub.1 pki---req.1 pki---self.1 \
+ pki---signcrl.1 pki---verify.1
CONFIG_CLEAN_VPATH_FILES =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
@@ -385,16 +385,17 @@ xml_CFLAGS = @xml_CFLAGS@
xml_LIBS = @xml_LIBS@
man1_MANS = \
pki.1 \
+ pki---acert.1 \
+ pki---dn.1 \
pki---gen.1 \
- pki---self.1 \
pki---issue.1 \
- pki---signcrl.1 \
- pki---acert.1 \
- pki---req.1 \
- pki---pkcs7.1 \
pki---keyid.1 \
+ pki---pkcs7.1 \
pki---print.1 \
pki---pub.1 \
+ pki---req.1 \
+ pki---self.1 \
+ pki---signcrl.1 \
pki---verify.1
CLEANFILES = $(man1_MANS)
@@ -433,16 +434,20 @@ $(ACLOCAL_M4): $(am__aclocal_m4_deps)
$(am__aclocal_m4_deps):
pki.1: $(top_builddir)/config.status $(srcdir)/pki.1.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+pki---acert.1: $(top_builddir)/config.status $(srcdir)/pki---acert.1.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+pki---dn.1: $(top_builddir)/config.status $(srcdir)/pki---dn.1.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
pki---gen.1: $(top_builddir)/config.status $(srcdir)/pki---gen.1.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
pki---issue.1: $(top_builddir)/config.status $(srcdir)/pki---issue.1.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
pki---keyid.1: $(top_builddir)/config.status $(srcdir)/pki---keyid.1.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
-pki---pkcs7.1: $(top_builddir)/config.status $(srcdir)/pki---pkcs7.1.in
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
pki---pkcs12.1: $(top_builddir)/config.status $(srcdir)/pki---pkcs12.1.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
+pki---pkcs7.1: $(top_builddir)/config.status $(srcdir)/pki---pkcs7.1.in
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
pki---print.1: $(top_builddir)/config.status $(srcdir)/pki---print.1.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
pki---pub.1: $(top_builddir)/config.status $(srcdir)/pki---pub.1.in
@@ -453,8 +458,6 @@ pki---self.1: $(top_builddir)/config.status $(srcdir)/pki---self.1.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
pki---signcrl.1: $(top_builddir)/config.status $(srcdir)/pki---signcrl.1.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
-pki---acert.1: $(top_builddir)/config.status $(srcdir)/pki---acert.1.in
- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
pki---verify.1: $(top_builddir)/config.status $(srcdir)/pki---verify.1.in
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@
diff --git a/src/pki/man/pki---dn.1.in b/src/pki/man/pki---dn.1.in
new file mode 100644
index 000000000..ce1210fdb
--- /dev/null
+++ b/src/pki/man/pki---dn.1.in
@@ -0,0 +1,56 @@
+.TH "PKI \-\-DN" 1 "2015-08-06" "@PACKAGE_VERSION@" "strongSwan"
+.
+.SH "NAME"
+.
+pki \-\-dn \- Extract the subject DN of an X.509 certificate
+.
+.SH "SYNOPSIS"
+.
+.SY pki\ \-\-dn
+.OP \-\-in file
+.OP \-\-format format
+.OP \-\-debug level
+.YS
+.
+.SY pki\ \-\-dn
+.BI \-\-options\~ file
+.YS
+.
+.SY "pki \-\-dn"
+.B \-h
+|
+.B \-\-help
+.YS
+.
+.SH "DESCRIPTION"
+.
+This sub-command of
+.BR pki (1)
+extracts the ASN.1-encoded subject DistinguishedName (DN) of an X.509
+certificate and exports it in different formats. This may be useful when
+strongSwan's identity parser is unable to produce the correct binary encoding
+from a string.
+.
+.SH "OPTIONS"
+.
+.TP
+.B "\-h, \-\-help"
+Print usage information with a summary of the available options.
+.TP
+.BI "\-v, \-\-debug " level
+Set debug level, default: 1.
+.TP
+.BI "\-+, \-\-options " file
+Read command line options from \fIfile\fR.
+.TP
+.BI "\-i, \-\-in " file
+Input file. If not given the input is read from \fISTDIN\fR.
+.TP
+.BI "\-t, \-\-format " format
+Output format. One of \fIconfig\fR (strongSwan configuration compatible),
+\fIhex\fR (hexadecimal encoding, no prefix), \fIbase64\fR (Base64 encoding,
+no prefix), \fIbin\fR (raw binary data), defaults to \fIconfig\fR.
+.
+.SH "SEE ALSO"
+.
+.BR pki (1)
diff --git a/src/pki/man/pki---issue.1.in b/src/pki/man/pki---issue.1.in
index 3a89059c8..20238b73d 100644
--- a/src/pki/man/pki---issue.1.in
+++ b/src/pki/man/pki---issue.1.in
@@ -67,8 +67,9 @@ Public key or PKCS#10 certificate request file to issue. If not given the
key/request is read from \fISTDIN\fR.
.TP
.BI "\-t, \-\-type " type
-Type of the input. Either \fIpub\fR for a public key, or \fIpkcs10\fR for a
-PKCS#10 certificate request, defaults to \fIpub\fR.
+Type of the input. One of \fIpub\fR (public key), \fIrsa\fR (RSA private key),
+\fIecdsa\fR (ECDSA private key), or \fIpkcs10\fR (PKCS#10 certificate request),
+defaults to \fIpub\fR.
.TP
.BI "\-k, \-\-cakey " file
CA private key file. Either this or
diff --git a/src/pki/man/pki.1.in b/src/pki/man/pki.1.in
index f347031b4..f1a2ae2c0 100644
--- a/src/pki/man/pki.1.in
+++ b/src/pki/man/pki.1.in
@@ -1,4 +1,4 @@
-.TH PKI 1 "2013-07-31" "@PACKAGE_VERSION@" "strongSwan"
+.TH PKI 1 "2015-08-06" "@PACKAGE_VERSION@" "strongSwan"
.
.SH "NAME"
.
@@ -64,6 +64,9 @@ Calculate key identifiers of a key or certificate.
.B "\-a, \-\-print"
Print a credential (key, certificate etc.) in human readable form.
.TP
+.B "\-d, \-\-dn"
+Extract the subject DN of an X.509 certificate.
+.TP
.B "\-p, \-\-pub"
Extract a public key from a private key or certificate.
.TP
@@ -156,5 +159,6 @@ certificates with the \-\-crl option.
.BR pki\ \-\-pkcs7 (1),
.BR pki\ \-\-keyid (1),
.BR pki\ \-\-print (1),
+.BR pki\ \-\-dn (1),
.BR pki\ \-\-pub (1),
.BR pki\ \-\-verify (1)
diff --git a/src/starter/netkey.c b/src/starter/netkey.c
index 2b500bab4..3eb6973a1 100644
--- a/src/starter/netkey.c
+++ b/src/starter/netkey.c
@@ -55,16 +55,3 @@ bool starter_netkey_init(void)
DBG2(DBG_APP, "found netkey IPsec stack");
return TRUE;
}
-
-void starter_netkey_cleanup(void)
-{
- if (!lib->plugins->load(lib->plugins,
- lib->settings->get_str(lib->settings, "starter.load", PLUGINS)))
- {
- DBG1(DBG_APP, "unable to load kernel plugins");
- return;
- }
- hydra->kernel_interface->flush_sas(hydra->kernel_interface);
- hydra->kernel_interface->flush_policies(hydra->kernel_interface);
- lib->plugins->unload(lib->plugins);
-}
diff --git a/src/starter/netkey.h b/src/starter/netkey.h
index c12924174..bc71af2ed 100644
--- a/src/starter/netkey.h
+++ b/src/starter/netkey.h
@@ -16,7 +16,6 @@
#define _STARTER_NETKEY_H_
extern bool starter_netkey_init (void);
-extern void starter_netkey_cleanup (void);
#endif /* _STARTER_NETKEY_H_ */
diff --git a/src/starter/parser/conf_parser.h b/src/starter/parser/conf_parser.h
index 20938201a..49131a0db 100644
--- a/src/starter/parser/conf_parser.h
+++ b/src/starter/parser/conf_parser.h
@@ -119,4 +119,4 @@ struct conf_parser_t {
*/
conf_parser_t *conf_parser_create(const char *file);
-#endif /** CONF_PARSER_H_ @}*/ \ No newline at end of file
+#endif /** CONF_PARSER_H_ @}*/
diff --git a/src/starter/parser/lexer.c b/src/starter/parser/lexer.c
index cebf5a06c..a0937710e 100644
--- a/src/starter/parser/lexer.c
+++ b/src/starter/parser/lexer.c
@@ -456,8 +456,8 @@ static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
yyg->yy_c_buf_p = yy_cp;
/* %% [4.0] data tables for the DFA and the user's section 1 definitions go here */
-#define YY_NUM_RULES 29
-#define YY_END_OF_BUFFER 30
+#define YY_NUM_RULES 26
+#define YY_END_OF_BUFFER 27
/* This struct is not used in this scanner,
but its presence is necessary. */
struct yy_trans_info
@@ -465,17 +465,16 @@ struct yy_trans_info
flex_int32_t yy_verify;
flex_int32_t yy_nxt;
};
-static yyconst flex_int16_t yy_accept[83] =
+static yyconst flex_int16_t yy_accept[80] =
{ 0,
- 0, 0, 0, 0, 0, 0, 30, 12, 3, 5,
+ 0, 0, 0, 0, 0, 0, 27, 12, 3, 5,
11, 4, 6, 12, 12, 2, 12, 12, 17, 13,
- 14, 15, 28, 19, 18, 20, 12, 3, 4, 4,
- 0, 12, 2, 0, 9, 12, 12, 17, 16, 28,
- 27, 26, 27, 24, 25, 21, 22, 23, 12, 0,
- 12, 12, 12, 0, 12, 8, 12, 12, 0, 12,
- 12, 12, 0, 12, 12, 12, 0, 0, 12, 0,
- 0, 0, 12, 0, 1, 10, 10, 0, 0, 0,
- 7, 0
+ 14, 15, 25, 18, 19, 12, 3, 4, 4, 0,
+ 12, 2, 0, 9, 12, 12, 17, 16, 25, 24,
+ 23, 24, 20, 21, 22, 12, 0, 12, 12, 12,
+ 0, 12, 8, 12, 12, 0, 12, 12, 12, 0,
+ 12, 12, 12, 0, 0, 12, 0, 0, 0, 12,
+ 0, 1, 10, 10, 0, 0, 0, 7, 0
} ;
static yyconst flex_int32_t yy_ec[256] =
@@ -489,11 +488,11 @@ static yyconst flex_int32_t yy_ec[256] =
8, 1, 1, 9, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 10, 1, 1, 1, 1, 11, 12, 13, 14,
+ 1, 10, 1, 1, 1, 1, 11, 1, 12, 13,
- 15, 16, 17, 1, 18, 1, 1, 19, 1, 20,
- 21, 22, 1, 23, 24, 25, 26, 27, 1, 1,
- 1, 1, 1, 1, 28, 1, 1, 1, 1, 1,
+ 14, 15, 16, 1, 17, 1, 1, 18, 1, 19,
+ 20, 21, 1, 22, 23, 24, 25, 26, 1, 1,
+ 1, 1, 1, 1, 27, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
@@ -510,110 +509,106 @@ static yyconst flex_int32_t yy_ec[256] =
1, 1, 1, 1, 1
} ;
-static yyconst flex_int32_t yy_meta[29] =
+static yyconst flex_int32_t yy_meta[28] =
{ 0,
1, 2, 3, 1, 2, 4, 2, 5, 1, 6,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1
+ 1, 1, 1, 1, 1, 1, 1
} ;
-static yyconst flex_int16_t yy_base[94] =
+static yyconst flex_int16_t yy_base[91] =
{ 0,
- 0, 17, 43, 52, 7, 26, 102, 0, 9, 189,
- 189, 0, 189, 93, 79, 36, 10, 83, 0, 189,
- 189, 59, 0, 189, 189, 85, 0, 32, 0, 0,
- 0, 83, 65, 80, 0, 74, 70, 0, 189, 0,
- 189, 189, 88, 189, 189, 189, 189, 189, 71, 63,
- 31, 61, 58, 59, 64, 0, 63, 66, 61, 61,
- 56, 60, 53, 64, 41, 10, 40, 32, 109, 66,
- 49, 27, 116, 37, 189, 189, 71, 8, 2, 5,
- 189, 189, 124, 130, 136, 142, 148, 154, 159, 164,
- 170, 176, 182
-
+ 0, 16, 41, 50, 4, 5, 101, 0, 24, 184,
+ 184, 0, 184, 92, 79, 32, 16, 83, 0, 184,
+ 184, 56, 0, 184, 81, 0, 33, 0, 0, 0,
+ 84, 62, 81, 0, 75, 71, 0, 184, 0, 184,
+ 184, 89, 184, 184, 184, 73, 68, 1, 66, 62,
+ 63, 65, 0, 64, 67, 62, 62, 57, 62, 55,
+ 67, 47, 63, 40, 31, 104, 68, 47, 35, 111,
+ 42, 184, 184, 69, 17, 7, 9, 184, 184, 119,
+ 125, 131, 137, 143, 149, 154, 159, 165, 171, 177
} ;
-static yyconst flex_int16_t yy_def[94] =
+static yyconst flex_int16_t yy_def[91] =
{ 0,
- 83, 83, 84, 84, 85, 85, 82, 86, 82, 82,
- 82, 87, 82, 86, 86, 82, 86, 86, 88, 82,
- 82, 82, 89, 82, 82, 90, 86, 82, 87, 87,
- 86, 86, 82, 82, 86, 86, 86, 88, 82, 89,
- 82, 82, 82, 82, 82, 82, 82, 82, 86, 82,
- 86, 86, 86, 82, 86, 86, 86, 86, 82, 86,
- 86, 86, 82, 86, 86, 86, 82, 82, 91, 92,
- 93, 82, 91, 93, 82, 82, 92, 82, 82, 82,
- 82, 0, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 82
-
+ 80, 80, 81, 81, 82, 82, 79, 83, 79, 79,
+ 79, 84, 79, 83, 83, 79, 83, 83, 85, 79,
+ 79, 79, 86, 79, 87, 83, 79, 84, 84, 83,
+ 83, 79, 79, 83, 83, 83, 85, 79, 86, 79,
+ 79, 79, 79, 79, 79, 83, 79, 83, 83, 83,
+ 79, 83, 83, 83, 83, 79, 83, 83, 83, 79,
+ 83, 83, 83, 79, 79, 88, 89, 90, 79, 88,
+ 90, 79, 79, 89, 79, 79, 79, 79, 0, 79,
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79
} ;
-static yyconst flex_int16_t yy_nxt[218] =
+static yyconst flex_int16_t yy_nxt[212] =
{ 0,
- 82, 9, 10, 82, 9, 11, 12, 13, 14, 24,
- 28, 70, 25, 28, 70, 29, 26, 15, 16, 10,
- 35, 16, 11, 12, 13, 14, 81, 80, 24, 17,
- 36, 25, 79, 28, 15, 26, 28, 33, 29, 75,
- 33, 78, 29, 18, 20, 20, 55, 20, 21, 20,
- 56, 75, 22, 20, 20, 72, 20, 21, 20, 71,
- 69, 22, 34, 39, 39, 39, 33, 77, 68, 33,
- 77, 29, 77, 67, 66, 77, 65, 64, 63, 62,
- 61, 60, 59, 58, 57, 54, 39, 42, 43, 53,
- 42, 34, 52, 51, 50, 49, 44, 37, 32, 31,
-
- 45, 82, 82, 82, 46, 82, 82, 47, 82, 48,
- 74, 75, 82, 74, 74, 74, 74, 74, 75, 82,
- 74, 74, 74, 74, 8, 8, 8, 8, 8, 8,
- 19, 19, 19, 19, 19, 19, 23, 23, 23, 23,
- 23, 23, 27, 82, 82, 82, 82, 27, 30, 30,
- 82, 30, 30, 30, 38, 82, 82, 82, 38, 40,
- 40, 82, 82, 40, 41, 41, 41, 41, 41, 41,
- 73, 73, 73, 73, 73, 73, 76, 76, 76, 76,
- 82, 76, 74, 74, 74, 74, 74, 74, 7, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
-
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 82
+ 79, 9, 10, 79, 9, 11, 12, 13, 14, 24,
+ 24, 79, 79, 25, 25, 52, 15, 16, 10, 53,
+ 16, 11, 12, 13, 14, 27, 34, 17, 27, 78,
+ 28, 77, 15, 32, 27, 35, 32, 27, 28, 28,
+ 76, 18, 20, 20, 72, 20, 21, 20, 75, 72,
+ 22, 20, 20, 69, 20, 21, 20, 33, 68, 22,
+ 38, 38, 38, 32, 67, 66, 32, 67, 28, 74,
+ 74, 65, 74, 74, 64, 63, 62, 61, 60, 59,
+ 58, 57, 38, 41, 42, 56, 55, 33, 54, 51,
+ 50, 41, 49, 48, 47, 46, 36, 31, 30, 43,
+
+ 79, 79, 44, 79, 45, 71, 72, 79, 71, 71,
+ 71, 71, 71, 72, 79, 71, 71, 71, 71, 8,
+ 8, 8, 8, 8, 8, 19, 19, 19, 19, 19,
+ 19, 23, 23, 23, 23, 23, 23, 26, 79, 79,
+ 79, 79, 26, 29, 29, 79, 29, 29, 29, 37,
+ 79, 79, 79, 37, 39, 39, 39, 79, 39, 40,
+ 40, 40, 40, 40, 40, 70, 70, 70, 70, 70,
+ 70, 73, 73, 73, 73, 79, 73, 71, 71, 71,
+ 71, 71, 71, 7, 79, 79, 79, 79, 79, 79,
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
+
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
+ 79
} ;
-static yyconst flex_int16_t yy_chk[218] =
+static yyconst flex_int16_t yy_chk[212] =
{ 0,
0, 1, 1, 0, 1, 1, 1, 1, 1, 5,
- 9, 66, 5, 9, 66, 9, 5, 1, 2, 2,
- 17, 2, 2, 2, 2, 2, 80, 79, 6, 2,
- 17, 6, 78, 28, 2, 6, 28, 16, 28, 74,
- 16, 72, 16, 2, 3, 3, 51, 3, 3, 3,
- 51, 71, 3, 4, 4, 68, 4, 4, 4, 67,
- 65, 4, 16, 22, 22, 22, 33, 70, 64, 33,
- 70, 33, 77, 63, 62, 77, 61, 60, 59, 58,
- 57, 55, 54, 53, 52, 50, 22, 26, 26, 49,
- 43, 33, 37, 36, 34, 32, 26, 18, 15, 14,
-
- 26, 7, 0, 0, 26, 0, 0, 26, 0, 26,
- 69, 69, 0, 69, 69, 69, 69, 73, 73, 0,
- 73, 73, 73, 73, 83, 83, 83, 83, 83, 83,
- 84, 84, 84, 84, 84, 84, 85, 85, 85, 85,
- 85, 85, 86, 0, 0, 0, 0, 86, 87, 87,
- 0, 87, 87, 87, 88, 0, 0, 0, 88, 89,
- 89, 0, 0, 89, 90, 90, 90, 90, 90, 90,
- 91, 91, 91, 91, 91, 91, 92, 92, 92, 92,
- 0, 92, 93, 93, 93, 93, 93, 93, 82, 82,
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
-
- 82, 82, 82, 82, 82, 82, 82, 82, 82, 82,
- 82, 82, 82, 82, 82, 82, 82
+ 6, 0, 0, 5, 6, 48, 1, 2, 2, 48,
+ 2, 2, 2, 2, 2, 9, 17, 2, 9, 77,
+ 9, 76, 2, 16, 27, 17, 16, 27, 16, 27,
+ 75, 2, 3, 3, 71, 3, 3, 3, 69, 68,
+ 3, 4, 4, 65, 4, 4, 4, 16, 64, 4,
+ 22, 22, 22, 32, 63, 62, 32, 63, 32, 67,
+ 74, 61, 67, 74, 60, 59, 58, 57, 56, 55,
+ 54, 52, 22, 25, 25, 51, 50, 32, 49, 47,
+ 46, 42, 36, 35, 33, 31, 18, 15, 14, 25,
+
+ 7, 0, 25, 0, 25, 66, 66, 0, 66, 66,
+ 66, 66, 70, 70, 0, 70, 70, 70, 70, 80,
+ 80, 80, 80, 80, 80, 81, 81, 81, 81, 81,
+ 81, 82, 82, 82, 82, 82, 82, 83, 0, 0,
+ 0, 0, 83, 84, 84, 0, 84, 84, 84, 85,
+ 0, 0, 0, 85, 86, 86, 86, 0, 86, 87,
+ 87, 87, 87, 87, 87, 88, 88, 88, 88, 88,
+ 88, 89, 89, 89, 89, 0, 89, 90, 90, 90,
+ 90, 90, 90, 79, 79, 79, 79, 79, 79, 79,
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
+
+ 79, 79, 79, 79, 79, 79, 79, 79, 79, 79,
+ 79
} ;
/* Table of booleans, true if rule could match eol. */
-static yyconst flex_int32_t yy_rule_can_match_eol[30] =
+static yyconst flex_int32_t yy_rule_can_match_eol[27] =
{ 0,
-0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1,
- 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, };
+0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 1, 0, 1, 0, };
-static yyconst flex_int16_t yy_rule_linenum[29] =
+static yyconst flex_int16_t yy_rule_linenum[26] =
{ 0,
60, 61, 62, 63, 65, 67, 68, 69, 70, 72,
- 77, 82, 90, 109, 112, 115, 118, 124, 126, 127,
- 150, 151, 152, 153, 154, 155, 156, 157
+ 77, 82, 90, 109, 112, 115, 118, 124, 126, 145,
+ 146, 147, 148, 149, 150
} ;
/* The intent behind this definition is that it'll catch
@@ -662,7 +657,7 @@ static void include_files(parser_helper_t *ctx);
/* state used to scan quoted strings */
-#line 666 "parser/lexer.c"
+#line 661 "parser/lexer.c"
#define INITIAL 0
#define inc 1
@@ -977,7 +972,7 @@ YY_DECL
#line 58 "parser/lexer.l"
-#line 981 "parser/lexer.c"
+#line 976 "parser/lexer.c"
yylval = yylval_param;
@@ -1043,13 +1038,13 @@ yy_match:
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 83 )
+ if ( yy_current_state >= 80 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
++yy_cp;
}
- while ( yy_base[yy_current_state] != 189 );
+ while ( yy_base[yy_current_state] != 184 );
yy_find_action:
/* %% [10.0] code to find the action number goes here */
@@ -1084,13 +1079,13 @@ do_action: /* This label is used only to access EOF actions. */
{
if ( yy_act == 0 )
fprintf( stderr, "--scanner backing up\n" );
- else if ( yy_act < 29 )
+ else if ( yy_act < 26 )
fprintf( stderr, "--accepting rule at line %ld (\"%s\")\n",
(long)yy_rule_linenum[yy_act], yytext );
- else if ( yy_act == 29 )
+ else if ( yy_act == 26 )
fprintf( stderr, "--accepting default rule (\"%s\")\n",
yytext );
- else if ( yy_act == 30 )
+ else if ( yy_act == 27 )
fprintf( stderr, "--(end of buffer or a NUL)\n" );
else
fprintf( stderr, "--EOF (start condition %d)\n", YY_START );
@@ -1246,21 +1241,13 @@ case 18:
case YY_STATE_EOF(str):
#line 125 "parser/lexer.l"
case 19:
-/* rule 19 can match eol */
-#line 127 "parser/lexer.l"
-case 20:
-/* rule 20 can match eol */
YY_RULE_SETUP
-#line 127 "parser/lexer.l"
+#line 126 "parser/lexer.l"
{
if (!streq(yytext, "\""))
{
- if (streq(yytext, "\n"))
- { /* put the newline back to fix the line numbers */
- unput('\n');
- yy_set_bol(0);
- }
PARSER_DBG1(yyextra, "unterminated string detected");
+ return STRING_ERROR;
}
if (yy_top_state(yyscanner) == inc)
{ /* string include */
@@ -1276,52 +1263,43 @@ YY_RULE_SETUP
}
}
YY_BREAK
-case 21:
+case 20:
YY_RULE_SETUP
-#line 150 "parser/lexer.l"
+#line 145 "parser/lexer.l"
yyextra->string_add(yyextra, "\n");
YY_BREAK
-case 22:
+case 21:
YY_RULE_SETUP
-#line 151 "parser/lexer.l"
+#line 146 "parser/lexer.l"
yyextra->string_add(yyextra, "\r");
YY_BREAK
-case 23:
+case 22:
YY_RULE_SETUP
-#line 152 "parser/lexer.l"
+#line 147 "parser/lexer.l"
yyextra->string_add(yyextra, "\t");
YY_BREAK
-case 24:
-YY_RULE_SETUP
-#line 153 "parser/lexer.l"
-yyextra->string_add(yyextra, "\b");
- YY_BREAK
-case 25:
-YY_RULE_SETUP
-#line 154 "parser/lexer.l"
-yyextra->string_add(yyextra, "\f");
- YY_BREAK
-case 26:
-/* rule 26 can match eol */
+case 23:
+/* rule 23 can match eol */
YY_RULE_SETUP
-#line 155 "parser/lexer.l"
+#line 148 "parser/lexer.l"
/* merge lines that end with EOL characters */
YY_BREAK
-case 27:
+case 24:
YY_RULE_SETUP
-#line 156 "parser/lexer.l"
+#line 149 "parser/lexer.l"
yyextra->string_add(yyextra, yytext+1);
YY_BREAK
-case 28:
+case 25:
+/* rule 25 can match eol */
YY_RULE_SETUP
-#line 157 "parser/lexer.l"
+#line 150 "parser/lexer.l"
{
yyextra->string_add(yyextra, yytext);
}
YY_BREAK
case YY_STATE_EOF(INITIAL):
-#line 162 "parser/lexer.l"
+#line 155 "parser/lexer.l"
{
conf_parser_pop_buffer_state(yyscanner);
if (!conf_parser_open_next_file(yyextra) && !YY_CURRENT_BUFFER)
@@ -1330,12 +1308,12 @@ case YY_STATE_EOF(INITIAL):
}
}
YY_BREAK
-case 29:
+case 26:
YY_RULE_SETUP
-#line 170 "parser/lexer.l"
+#line 163 "parser/lexer.l"
YY_FATAL_ERROR( "flex scanner jammed" );
YY_BREAK
-#line 1339 "parser/lexer.c"
+#line 1317 "parser/lexer.c"
case YY_END_OF_BUFFER:
{
@@ -1649,7 +1627,7 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 83 )
+ if ( yy_current_state >= 80 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
@@ -1683,11 +1661,11 @@ static int yy_get_next_buffer (yyscan_t yyscanner)
while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
{
yy_current_state = (int) yy_def[yy_current_state];
- if ( yy_current_state >= 83 )
+ if ( yy_current_state >= 80 )
yy_c = yy_meta[(unsigned int) yy_c];
}
yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
- yy_is_jam = (yy_current_state == 82);
+ yy_is_jam = (yy_current_state == 79);
return yy_is_jam ? 0 : yy_current_state;
}
@@ -2705,7 +2683,7 @@ void conf_parser_free (void * ptr , yyscan_t yyscanner)
/* %ok-for-header */
-#line 170 "parser/lexer.l"
+#line 163 "parser/lexer.l"
diff --git a/src/starter/parser/lexer.l b/src/starter/parser/lexer.l
index d967e745b..f70658e68 100644
--- a/src/starter/parser/lexer.l
+++ b/src/starter/parser/lexer.l
@@ -123,16 +123,11 @@ static void include_files(parser_helper_t *ctx);
<str>{
"\"" |
<<EOF>> |
- \n |
\\ {
if (!streq(yytext, "\""))
{
- if (streq(yytext, "\n"))
- { /* put the newline back to fix the line numbers */
- unput('\n');
- yy_set_bol(0);
- }
PARSER_DBG1(yyextra, "unterminated string detected");
+ return STRING_ERROR;
}
if (yy_top_state(yyscanner) == inc)
{ /* string include */
@@ -150,11 +145,9 @@ static void include_files(parser_helper_t *ctx);
\\n yyextra->string_add(yyextra, "\n");
\\r yyextra->string_add(yyextra, "\r");
\\t yyextra->string_add(yyextra, "\t");
- \\b yyextra->string_add(yyextra, "\b");
- \\f yyextra->string_add(yyextra, "\f");
\\\r?\n /* merge lines that end with EOL characters */
\\. yyextra->string_add(yyextra, yytext+1);
- [^\\\n"]+ {
+ [^\\"]+ {
yyextra->string_add(yyextra, yytext);
}
}
diff --git a/src/starter/parser/parser.c b/src/starter/parser/parser.c
index 8cf3fe19e..41ab515cb 100644
--- a/src/starter/parser/parser.c
+++ b/src/starter/parser/parser.c
@@ -166,7 +166,8 @@ extern int conf_parser_debug;
NEWLINE = 261,
CONFIG_SETUP = 262,
CONN = 263,
- CA = 264
+ CA = 264,
+ STRING_ERROR = 265
};
#endif
/* Tokens. */
@@ -177,6 +178,7 @@ extern int conf_parser_debug;
#define CONFIG_SETUP 262
#define CONN 263
#define CA 264
+#define STRING_ERROR 265
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
@@ -188,7 +190,7 @@ union YYSTYPE
char *s;
conf_parser_section_t t;
-#line 192 "parser/parser.c" /* yacc.c:355 */
+#line 194 "parser/parser.c" /* yacc.c:355 */
};
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
@@ -202,7 +204,7 @@ int conf_parser_parse (parser_helper_t *ctx);
/* Copy the second part of user declarations. */
-#line 206 "parser/parser.c" /* yacc.c:358 */
+#line 208 "parser/parser.c" /* yacc.c:358 */
#ifdef short
# undef short
@@ -447,7 +449,7 @@ union yyalloc
#define YYLAST 11
/* YYNTOKENS -- Number of terminals. */
-#define YYNTOKENS 10
+#define YYNTOKENS 11
/* YYNNTS -- Number of nonterminals. */
#define YYNNTS 8
/* YYNRULES -- Number of rules. */
@@ -458,7 +460,7 @@ union yyalloc
/* YYTRANSLATE[YYX] -- Symbol number corresponding to YYX as returned
by yylex, with out-of-bounds checking. */
#define YYUNDEFTOK 2
-#define YYMAXUTOK 264
+#define YYMAXUTOK 265
#define YYTRANSLATE(YYX) \
((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -493,7 +495,7 @@ static const yytype_uint8 yytranslate[] =
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
- 5, 6, 7, 8, 9
+ 5, 6, 7, 8, 9, 10
};
#if YYDEBUG
@@ -511,8 +513,9 @@ static const yytype_uint8 yyrline[] =
static const char *const yytname[] =
{
"$end", "error", "$undefined", "STRING", "EQ", "SPACES", "NEWLINE",
- "CONFIG_SETUP", "CONN", "CA", "$accept", "statements", "statement",
- "section", "section_type", "section_name", "setting", "value", YY_NULLPTR
+ "CONFIG_SETUP", "CONN", "CA", "STRING_ERROR", "$accept", "statements",
+ "statement", "section", "section_type", "section_name", "setting",
+ "value", YY_NULLPTR
};
#endif
@@ -521,7 +524,8 @@ static const char *const yytname[] =
(internal) symbol number NUM (which must be that of a token). */
static const yytype_uint16 yytoknum[] =
{
- 0, 256, 257, 258, 259, 260, 261, 262, 263, 264
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265
};
# endif
@@ -583,15 +587,15 @@ static const yytype_int8 yycheck[] =
symbol of state STATE-NUM. */
static const yytype_uint8 yystos[] =
{
- 0, 11, 0, 5, 6, 7, 8, 9, 12, 13,
- 14, 3, 16, 3, 15, 4, 3, 17, 3
+ 0, 12, 0, 5, 6, 7, 8, 9, 13, 14,
+ 15, 3, 17, 3, 16, 4, 3, 18, 3
};
/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
static const yytype_uint8 yyr1[] =
{
- 0, 10, 11, 11, 11, 12, 12, 13, 14, 14,
- 14, 15, 15, 16, 16, 16, 16, 17, 17
+ 0, 11, 12, 12, 12, 13, 13, 14, 15, 15,
+ 15, 16, 16, 17, 17, 17, 17, 18, 18
};
/* YYR2[YYN] -- Number of symbols on the right hand side of rule YYN. */
@@ -1026,19 +1030,19 @@ yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, parser_helper_t *c
case 3: /* STRING */
#line 86 "parser/parser.y" /* yacc.c:1257 */
{ free(((*yyvaluep).s)); }
-#line 1030 "parser/parser.c" /* yacc.c:1257 */
+#line 1034 "parser/parser.c" /* yacc.c:1257 */
break;
- case 15: /* section_name */
+ case 16: /* section_name */
#line 86 "parser/parser.y" /* yacc.c:1257 */
{ free(((*yyvaluep).s)); }
-#line 1036 "parser/parser.c" /* yacc.c:1257 */
+#line 1040 "parser/parser.c" /* yacc.c:1257 */
break;
- case 17: /* value */
+ case 18: /* value */
#line 86 "parser/parser.y" /* yacc.c:1257 */
{ free(((*yyvaluep).s)); }
-#line 1042 "parser/parser.c" /* yacc.c:1257 */
+#line 1046 "parser/parser.c" /* yacc.c:1257 */
break;
@@ -1315,7 +1319,7 @@ yyreduce:
conf_parser_t *parser = (conf_parser_t*)ctx->context;
parser->add_section(parser, (yyvsp[-1].t), (yyvsp[0].s));
}
-#line 1319 "parser/parser.c" /* yacc.c:1646 */
+#line 1323 "parser/parser.c" /* yacc.c:1646 */
break;
case 8:
@@ -1323,7 +1327,7 @@ yyreduce:
{
(yyval.t) = CONF_PARSER_CONFIG_SETUP;
}
-#line 1327 "parser/parser.c" /* yacc.c:1646 */
+#line 1331 "parser/parser.c" /* yacc.c:1646 */
break;
case 9:
@@ -1331,7 +1335,7 @@ yyreduce:
{
(yyval.t) = CONF_PARSER_CONN;
}
-#line 1335 "parser/parser.c" /* yacc.c:1646 */
+#line 1339 "parser/parser.c" /* yacc.c:1646 */
break;
case 10:
@@ -1339,7 +1343,7 @@ yyreduce:
{
(yyval.t) = CONF_PARSER_CA;
}
-#line 1343 "parser/parser.c" /* yacc.c:1646 */
+#line 1347 "parser/parser.c" /* yacc.c:1646 */
break;
case 11:
@@ -1347,7 +1351,7 @@ yyreduce:
{
(yyval.s) = NULL;
}
-#line 1351 "parser/parser.c" /* yacc.c:1646 */
+#line 1355 "parser/parser.c" /* yacc.c:1646 */
break;
case 12:
@@ -1355,7 +1359,7 @@ yyreduce:
{
(yyval.s) = (yyvsp[0].s);
}
-#line 1359 "parser/parser.c" /* yacc.c:1646 */
+#line 1363 "parser/parser.c" /* yacc.c:1646 */
break;
case 14:
@@ -1371,7 +1375,7 @@ yyreduce:
conf_parser_t *parser = (conf_parser_t*)ctx->context;
parser->add_setting(parser, (yyvsp[-2].s), (yyvsp[0].s));
}
-#line 1375 "parser/parser.c" /* yacc.c:1646 */
+#line 1379 "parser/parser.c" /* yacc.c:1646 */
break;
case 15:
@@ -1386,7 +1390,7 @@ yyreduce:
conf_parser_t *parser = (conf_parser_t*)ctx->context;
parser->add_setting(parser, (yyvsp[-1].s), NULL);
}
-#line 1390 "parser/parser.c" /* yacc.c:1646 */
+#line 1394 "parser/parser.c" /* yacc.c:1646 */
break;
case 16:
@@ -1396,7 +1400,7 @@ yyreduce:
free((yyvsp[0].s));
YYERROR;
}
-#line 1400 "parser/parser.c" /* yacc.c:1646 */
+#line 1404 "parser/parser.c" /* yacc.c:1646 */
break;
case 18:
@@ -1411,11 +1415,11 @@ yyreduce:
free((yyvsp[-1].s));
free((yyvsp[0].s));
}
-#line 1415 "parser/parser.c" /* yacc.c:1646 */
+#line 1419 "parser/parser.c" /* yacc.c:1646 */
break;
-#line 1419 "parser/parser.c" /* yacc.c:1646 */
+#line 1423 "parser/parser.c" /* yacc.c:1646 */
default: break;
}
/* User semantic actions sometimes alter yychar, and that requires
diff --git a/src/starter/parser/parser.h b/src/starter/parser/parser.h
index c10547be8..ed6ed2bf5 100644
--- a/src/starter/parser/parser.h
+++ b/src/starter/parser/parser.h
@@ -51,7 +51,8 @@ extern int conf_parser_debug;
NEWLINE = 261,
CONFIG_SETUP = 262,
CONN = 263,
- CA = 264
+ CA = 264,
+ STRING_ERROR = 265
};
#endif
/* Tokens. */
@@ -62,6 +63,7 @@ extern int conf_parser_debug;
#define CONFIG_SETUP 262
#define CONN 263
#define CA 264
+#define STRING_ERROR 265
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
@@ -73,7 +75,7 @@ union YYSTYPE
char *s;
conf_parser_section_t t;
-#line 77 "parser/parser.h" /* yacc.c:1909 */
+#line 79 "parser/parser.h" /* yacc.c:1909 */
};
# define YYSTYPE_IS_TRIVIAL 1
# define YYSTYPE_IS_DECLARED 1
diff --git a/src/starter/parser/parser.y b/src/starter/parser/parser.y
index 54dedc12b..0b2b3b09f 100644
--- a/src/starter/parser/parser.y
+++ b/src/starter/parser/parser.y
@@ -73,7 +73,7 @@ static int yylex(YYSTYPE *lvalp, parser_helper_t *ctx)
conf_parser_section_t t;
}
%token <s> STRING
-%token EQ SPACES NEWLINE CONFIG_SETUP CONN CA
+%token EQ SPACES NEWLINE CONFIG_SETUP CONN CA STRING_ERROR
/* ...and other symbols */
%type <t> section_type
diff --git a/src/starter/starter.c b/src/starter/starter.c
index a19298923..ab1ebdd5d 100644
--- a/src/starter/starter.c
+++ b/src/starter/starter.c
@@ -703,7 +703,6 @@ int main (int argc, char **argv)
{
starter_stop_charon();
}
- starter_netkey_cleanup();
confread_free(cfg);
unlink(starter_pid_file);
cleanup();
diff --git a/src/starter/starterstroke.c b/src/starter/starterstroke.c
index 79a92cdad..b92c00c87 100644
--- a/src/starter/starterstroke.c
+++ b/src/starter/starterstroke.c
@@ -16,6 +16,7 @@
#include <unistd.h>
#include <stdlib.h>
+#include <stdint.h>
#include <string.h>
#include <credentials/auth_cfg.h>
diff --git a/src/starter/tests/suites/test_parser.c b/src/starter/tests/suites/test_parser.c
index 26a41ba55..4ae7b22fa 100644
--- a/src/starter/tests/suites/test_parser.c
+++ b/src/starter/tests/suites/test_parser.c
@@ -328,6 +328,9 @@ static struct {
{ TRUE, "conn foo\n\tkey=val ue", "foo", "val ue" },
{ TRUE, "conn foo\n\tkey=\"val ue\"", "foo", "val ue" },
{ TRUE, "conn foo\n\tkey=\"val\\nue\"", "foo", "val\nue" },
+ { TRUE, "conn foo\n\tkey=\"val\nue\"", "foo", "val\nue" },
+ { TRUE, "conn foo\n\tkey=\"val\\\nue\"", "foo", "value" },
+ { FALSE, "conn foo\n\tkey=\"unterminated", "foo", NULL },
};
START_TEST(test_strings)
diff --git a/src/stroke/stroke.c b/src/stroke/stroke.c
index 07911d2d2..2dfb66d7c 100644
--- a/src/stroke/stroke.c
+++ b/src/stroke/stroke.c
@@ -17,6 +17,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
+#include <stdint.h>
#include <string.h>
#include <getopt.h>
diff --git a/src/swanctl/Makefile.am b/src/swanctl/Makefile.am
index f4f9fdf7e..703e5746a 100644
--- a/src/swanctl/Makefile.am
+++ b/src/swanctl/Makefile.am
@@ -7,10 +7,12 @@ swanctl_SOURCES = \
commands/install.c \
commands/list_sas.c \
commands/list_pols.c \
+ commands/list_authorities.c \
commands/list_conns.c \
commands/list_certs.c \
commands/list_pools.c \
commands/load_all.c \
+ commands/load_authorities.h commands/load_authorities.c \
commands/load_conns.c commands/load_conns.h \
commands/load_creds.c commands/load_creds.h \
commands/load_pools.c commands/load_pools.h \
@@ -46,7 +48,7 @@ CLEANFILES = $(man_MANS)
swanctl.conf.5.main: swanctl.opt
$(AM_V_GEN) \
- $(PYTHON) $(top_srcdir)/conf/format-options.py -n -f man swanctl.opt > $(srcdir)/$@
+ cd $(srcdir) && $(PYTHON) $(abs_top_srcdir)/conf/format-options.py -n -f man swanctl.opt > $@
swanctl.conf.5: swanctl.conf.5.head swanctl.conf.5.main swanctl.conf.5.tail
$(AM_V_GEN) \
diff --git a/src/swanctl/Makefile.in b/src/swanctl/Makefile.in
index f981bb1f3..a4d853cb1 100644
--- a/src/swanctl/Makefile.in
+++ b/src/swanctl/Makefile.in
@@ -107,8 +107,10 @@ am__dirstamp = $(am__leading_dot)dirstamp
am_swanctl_OBJECTS = command.$(OBJEXT) commands/initiate.$(OBJEXT) \
commands/terminate.$(OBJEXT) commands/install.$(OBJEXT) \
commands/list_sas.$(OBJEXT) commands/list_pols.$(OBJEXT) \
+ commands/list_authorities.$(OBJEXT) \
commands/list_conns.$(OBJEXT) commands/list_certs.$(OBJEXT) \
commands/list_pools.$(OBJEXT) commands/load_all.$(OBJEXT) \
+ commands/load_authorities.$(OBJEXT) \
commands/load_conns.$(OBJEXT) commands/load_creds.$(OBJEXT) \
commands/load_pools.$(OBJEXT) commands/log.$(OBJEXT) \
commands/version.$(OBJEXT) commands/stats.$(OBJEXT) \
@@ -445,10 +447,12 @@ swanctl_SOURCES = \
commands/install.c \
commands/list_sas.c \
commands/list_pols.c \
+ commands/list_authorities.c \
commands/list_conns.c \
commands/list_certs.c \
commands/list_pools.c \
commands/load_all.c \
+ commands/load_authorities.h commands/load_authorities.c \
commands/load_conns.c commands/load_conns.h \
commands/load_creds.c commands/load_creds.h \
commands/load_pools.c commands/load_pools.h \
@@ -581,6 +585,8 @@ commands/list_sas.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
commands/list_pols.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
+commands/list_authorities.$(OBJEXT): commands/$(am__dirstamp) \
+ commands/$(DEPDIR)/$(am__dirstamp)
commands/list_conns.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
commands/list_certs.$(OBJEXT): commands/$(am__dirstamp) \
@@ -589,6 +595,8 @@ commands/list_pools.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
commands/load_all.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
+commands/load_authorities.$(OBJEXT): commands/$(am__dirstamp) \
+ commands/$(DEPDIR)/$(am__dirstamp)
commands/load_conns.$(OBJEXT): commands/$(am__dirstamp) \
commands/$(DEPDIR)/$(am__dirstamp)
commands/load_creds.$(OBJEXT): commands/$(am__dirstamp) \
@@ -619,12 +627,14 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/swanctl.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/initiate.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/install.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/list_authorities.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/list_certs.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/list_conns.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/list_pols.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/list_pools.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/list_sas.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/load_all.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/load_authorities.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/load_conns.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/load_creds.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@commands/$(DEPDIR)/load_pools.Po@am__quote@
@@ -977,7 +987,7 @@ swanctl.o : $(top_builddir)/config.status
swanctl.conf.5.main: swanctl.opt
$(AM_V_GEN) \
- $(PYTHON) $(top_srcdir)/conf/format-options.py -n -f man swanctl.opt > $(srcdir)/$@
+ cd $(srcdir) && $(PYTHON) $(abs_top_srcdir)/conf/format-options.py -n -f man swanctl.opt > $@
swanctl.conf.5: swanctl.conf.5.head swanctl.conf.5.main swanctl.conf.5.tail
$(AM_V_GEN) \
diff --git a/src/swanctl/command.c b/src/swanctl/command.c
index 03cd8b959..26c41346c 100644
--- a/src/swanctl/command.c
+++ b/src/swanctl/command.c
@@ -211,7 +211,7 @@ int command_usage(char *error, ...)
{
for (i = 0; i < MAX_COMMANDS && cmds[i].cmd; i++)
{
- fprintf(out, " swanctl --%-15s (-%c) %s\n",
+ fprintf(out, " swanctl --%-16s (-%c) %s\n",
cmds[i].cmd, cmds[i].op, cmds[i].description);
}
}
diff --git a/src/swanctl/command.h b/src/swanctl/command.h
index ffc319085..0760d1384 100644
--- a/src/swanctl/command.h
+++ b/src/swanctl/command.h
@@ -27,7 +27,7 @@
/**
* Maximum number of commands (+1).
*/
-#define MAX_COMMANDS 19
+#define MAX_COMMANDS 21
/**
* Maximum number of options in a command (+3)
diff --git a/src/swanctl/commands/list_authorities.c b/src/swanctl/commands/list_authorities.c
new file mode 100644
index 000000000..8bff6f95d
--- /dev/null
+++ b/src/swanctl/commands/list_authorities.c
@@ -0,0 +1,169 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+
+#include "command.h"
+
+#define LABELED_CRL_URI (1 << 0)
+#define LABELED_OCSP_URI (1 << 1)
+
+CALLBACK(authority_kv, int,
+ void *null, vici_res_t *res, char *name, void *value, int len)
+{
+ chunk_t chunk;
+
+ chunk = chunk_create(value, len);
+ if (chunk_printable(chunk, NULL, ' '))
+ {
+ printf(" %s: %.*s\n", name, len, value);
+ }
+
+ return 0;
+}
+
+
+CALLBACK(authority_list, int,
+ int *labeled, vici_res_t *res, char *name, void *value, int len)
+{
+ chunk_t chunk;
+
+ chunk = chunk_create(value, len);
+ if (chunk_printable(chunk, NULL, ' '))
+ {
+ if (streq(name, "crl_uris"))
+ {
+ printf(" %s %.*s\n",
+ (*labeled & LABELED_CRL_URI) ? " " : "crl_uris: ",
+ len, value);
+ *labeled |= LABELED_CRL_URI;
+ }
+ if (streq(name, "ocsp_uris"))
+ {
+ printf(" %s %.*s\n",
+ (*labeled & LABELED_OCSP_URI) ? " " : "ocsp_uris:",
+ len, value);
+ *labeled %= LABELED_OCSP_URI;
+ }
+ }
+ return 0;
+}
+
+CALLBACK(authorities, int,
+ void *null, vici_res_t *res, char *name)
+{
+ int labeled = 0;
+
+ printf("%s:\n", name);
+
+ return vici_parse_cb(res, NULL, authority_kv, authority_list, &labeled);
+}
+
+CALLBACK(list_cb, void,
+ command_format_options_t *format, char *name, vici_res_t *res)
+{
+ if (*format & COMMAND_FORMAT_RAW)
+ {
+ vici_dump(res, "list-authorities event", *format & COMMAND_FORMAT_PRETTY,
+ stdout);
+ }
+ else
+ {
+ if (vici_parse_cb(res, authorities, NULL, NULL, NULL) != 0)
+ {
+ fprintf(stderr, "parsing authority event failed: %s\n",
+ strerror(errno));
+ }
+ }
+}
+
+static int list_authorities(vici_conn_t *conn)
+{
+ vici_req_t *req;
+ vici_res_t *res;
+ command_format_options_t format = COMMAND_FORMAT_NONE;
+ char *arg, *ca_name = NULL;;
+ int ret = 0;
+
+ while (TRUE)
+ {
+ switch (command_getopt(&arg))
+ {
+ case 'h':
+ return command_usage(NULL);
+ case 'n':
+ ca_name = arg;
+ continue;
+ case 'P':
+ format |= COMMAND_FORMAT_PRETTY;
+ /* fall through to raw */
+ case 'r':
+ format |= COMMAND_FORMAT_RAW;
+ continue;
+ case EOF:
+ break;
+ default:
+ return command_usage("invalid --list-authorities option");
+ }
+ break;
+ }
+ if (vici_register(conn, "list-authority", list_cb, &format) != 0)
+ {
+ ret = errno;
+ fprintf(stderr, "registering for authorities failed: %s\n",
+ strerror(errno));
+ return ret;
+ }
+
+ req = vici_begin("list-authorities");
+ if (ca_name)
+ {
+ vici_add_key_valuef(req, "name", "%s", ca_name);
+ }
+ res = vici_submit(req, conn);
+ if (!res)
+ {
+ ret = errno;
+ fprintf(stderr, "list-authorities request failed: %s\n", strerror(errno));
+ return ret;
+ }
+ if (format & COMMAND_FORMAT_RAW)
+ {
+ vici_dump(res, "list-authorities reply", format & COMMAND_FORMAT_PRETTY,
+ stdout);
+ }
+ vici_free_res(res);
+ return 0;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+ command_register((command_t) {
+ list_authorities, 'B', "list-authorities",
+ "list loaded authority configurations",
+ {"[--raw|--pretty]"},
+ {
+ {"help", 'h', 0, "show usage information"},
+ {"name", 'n', 1, "filter by authority name"},
+ {"raw", 'r', 0, "dump raw response message"},
+ {"pretty", 'P', 0, "dump raw response message in pretty print"},
+ }
+ });
+}
diff --git a/src/swanctl/commands/list_certs.c b/src/swanctl/commands/list_certs.c
index ecb65289a..167f8d848 100644
--- a/src/swanctl/commands/list_certs.c
+++ b/src/swanctl/commands/list_certs.c
@@ -2,6 +2,9 @@
* Copyright (C) 2014 Martin Willi
* Copyright (C) 2014 revosec AG
*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
@@ -388,7 +391,7 @@ static void print_crl(crl_t *crl)
chunk = chunk_skip_zero(chunk);
localtime_r(&ts, &tm);
strftime(buf, sizeof(buf), "%F %T", &tm);
- printf(" %#B %N %s\n", &chunk, crl_reason_names, reason, buf);
+ printf(" %#B: %s, %N\n", &chunk, buf, crl_reason_names, reason);
count++;
}
enumerator->destroy(enumerator);
diff --git a/src/swanctl/commands/load_all.c b/src/swanctl/commands/load_all.c
index f47fee5b4..0010ce140 100644
--- a/src/swanctl/commands/load_all.c
+++ b/src/swanctl/commands/load_all.c
@@ -22,6 +22,7 @@
#include "command.h"
#include "swanctl.h"
#include "load_creds.h"
+#include "load_authorities.h"
#include "load_pools.h"
#include "load_conns.h"
@@ -72,6 +73,10 @@ static int load_all(vici_conn_t *conn)
}
if (ret == 0)
{
+ ret = load_authorities_cfg(conn, format, cfg);
+ }
+ if (ret == 0)
+ {
ret = load_pools_cfg(conn, format, cfg);
}
if (ret == 0)
@@ -90,7 +95,8 @@ static int load_all(vici_conn_t *conn)
static void __attribute__ ((constructor))reg()
{
command_register((command_t) {
- load_all, 'q', "load-all", "load credentials, pools and connections",
+ load_all, 'q', "load-all",
+ "load credentials, authorities, pools and connections",
{"[--raw|--pretty] [--clear] [--noprompt]"},
{
{"help", 'h', 0, "show usage information"},
diff --git a/src/swanctl/commands/load_authorities.c b/src/swanctl/commands/load_authorities.c
new file mode 100644
index 000000000..88dde6aaf
--- /dev/null
+++ b/src/swanctl/commands/load_authorities.c
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 2015 Andreas Steffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * 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.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "command.h"
+#include "swanctl.h"
+#include "load_authorities.h"
+
+/**
+ * Add a vici list from a comma separated string value
+ */
+static void add_list_key(vici_req_t *req, char *key, char *value)
+{
+ enumerator_t *enumerator;
+ char *token;
+
+ vici_begin_list(req, key);
+ enumerator = enumerator_create_token(value, ",", " ");
+ while (enumerator->enumerate(enumerator, &token))
+ {
+ vici_add_list_itemf(req, "%s", token);
+ }
+ enumerator->destroy(enumerator);
+ vici_end_list(req);
+}
+
+/**
+ * Add a vici certificate blob value given by its file patch
+ */
+static bool add_file_key_value(vici_req_t *req, char *key, char *value)
+{
+ chunk_t *map;
+ char *path, buf[PATH_MAX];
+
+ if (path_absolute(value))
+ {
+ path = value;
+ }
+ else
+ {
+ path = buf;
+ snprintf(path, PATH_MAX, "%s%s%s",
+ SWANCTL_X509CADIR, DIRECTORY_SEPARATOR, value);
+ }
+ map = chunk_map(path, FALSE);
+
+ if (map)
+ {
+ vici_add_key_value(req, key, map->ptr, map->len);
+ chunk_unmap(map);
+ return TRUE;
+ }
+ else
+ {
+ fprintf(stderr, "loading ca certificate '%s' failed: %s\n",
+ path, strerror(errno));
+ return FALSE;
+ }
+}
+
+/**
+ * Translate sletting key/values from a section into vici key-values/lists
+ */
+static bool add_key_values(vici_req_t *req, settings_t *cfg, char *section)
+{
+ enumerator_t *enumerator;
+ char *key, *value;
+ bool ret = TRUE;
+
+ enumerator = cfg->create_key_value_enumerator(cfg, section);
+ while (enumerator->enumerate(enumerator, &key, &value))
+ {
+ /* pool subnet is encoded as key/value, all other attributes as list */
+ if (streq(key, "cacert"))
+ {
+ ret = add_file_key_value(req, key, value);
+ }
+ else if (streq(key, "cert_uri_base"))
+ {
+ vici_add_key_valuef(req, key, "%s", value);
+ }
+ else
+ {
+ add_list_key(req, key, value);
+ }
+ if (!ret)
+ {
+ break;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ return ret;
+}
+
+/**
+ * Load an authority configuration
+ */
+static bool load_authority(vici_conn_t *conn, settings_t *cfg,
+ char *section, command_format_options_t format)
+{
+ vici_req_t *req;
+ vici_res_t *res;
+ bool ret = TRUE;
+ char buf[128];
+
+ snprintf(buf, sizeof(buf), "%s.%s", "authorities", section);
+
+ req = vici_begin("load-authority");
+
+ vici_begin_section(req, section);
+ if (!add_key_values(req, cfg, buf))
+ {
+ vici_free_req(req);
+ return FALSE;
+ }
+ vici_end_section(req);
+
+ res = vici_submit(req, conn);
+ if (!res)
+ {
+ fprintf(stderr, "load-authority request failed: %s\n", strerror(errno));
+ return FALSE;
+ }
+ if (format & COMMAND_FORMAT_RAW)
+ {
+ vici_dump(res, "load-authority reply", format & COMMAND_FORMAT_PRETTY,
+ stdout);
+ }
+ else if (!streq(vici_find_str(res, "no", "success"), "yes"))
+ {
+ fprintf(stderr, "loading authority '%s' failed: %s\n",
+ section, vici_find_str(res, "", "errmsg"));
+ ret = FALSE;
+ }
+ else
+ {
+ printf("loaded authority '%s'\n", section);
+ }
+ vici_free_res(res);
+ return ret;
+}
+
+CALLBACK(list_authority, int,
+ linked_list_t *list, vici_res_t *res, char *name, void *value, int len)
+{
+ if (streq(name, "authorities"))
+ {
+ char *str;
+
+ if (asprintf(&str, "%.*s", len, value) != -1)
+ {
+ list->insert_last(list, str);
+ }
+ }
+ return 0;
+}
+
+/**
+ * Create a list of currently loaded authorities
+ */
+static linked_list_t* list_authorities(vici_conn_t *conn,
+ command_format_options_t format)
+{
+ linked_list_t *list;
+ vici_res_t *res;
+
+ list = linked_list_create();
+
+ res = vici_submit(vici_begin("get-authorities"), conn);
+ if (res)
+ {
+ if (format & COMMAND_FORMAT_RAW)
+ {
+ vici_dump(res, "get-authorities reply", format & COMMAND_FORMAT_PRETTY,
+ stdout);
+ }
+ vici_parse_cb(res, NULL, NULL, list_authority, list);
+ vici_free_res(res);
+ }
+ return list;
+}
+
+/**
+ * Remove and free a string from a list
+ */
+static void remove_from_list(linked_list_t *list, char *str)
+{
+ enumerator_t *enumerator;
+ char *current;
+
+ enumerator = list->create_enumerator(list);
+ while (enumerator->enumerate(enumerator, &current))
+ {
+ if (streq(current, str))
+ {
+ list->remove_at(list, enumerator);
+ free(current);
+ }
+ }
+ enumerator->destroy(enumerator);
+}
+
+/**
+ * Unload a authority by name
+ */
+static bool unload_authority(vici_conn_t *conn, char *name,
+ command_format_options_t format)
+{
+ vici_req_t *req;
+ vici_res_t *res;
+ bool ret = TRUE;
+
+ req = vici_begin("unload-authority");
+ vici_add_key_valuef(req, "name", "%s", name);
+ res = vici_submit(req, conn);
+ if (!res)
+ {
+ fprintf(stderr, "unload-authority request failed: %s\n", strerror(errno));
+ return FALSE;
+ }
+ if (format & COMMAND_FORMAT_RAW)
+ {
+ vici_dump(res, "unload-authority reply", format & COMMAND_FORMAT_PRETTY,
+ stdout);
+ }
+ else if (!streq(vici_find_str(res, "no", "success"), "yes"))
+ {
+ fprintf(stderr, "unloading authority '%s' failed: %s\n",
+ name, vici_find_str(res, "", "errmsg"));
+ ret = FALSE;
+ }
+ vici_free_res(res);
+ return ret;
+}
+
+/**
+ * See header.
+ */
+int load_authorities_cfg(vici_conn_t *conn, command_format_options_t format,
+ settings_t *cfg)
+{
+ u_int found = 0, loaded = 0, unloaded = 0;
+ char *section;
+ enumerator_t *enumerator;
+ linked_list_t *authorities;
+
+ authorities = list_authorities(conn, format);
+
+ enumerator = cfg->create_section_enumerator(cfg, "authorities");
+ while (enumerator->enumerate(enumerator, &section))
+ {
+ remove_from_list(authorities, section);
+ found++;
+ if (load_authority(conn, cfg, section, format))
+ {
+ loaded++;
+ }
+ }
+ enumerator->destroy(enumerator);
+
+ /* unload all authorities in daemon, but not in file */
+ while (authorities->remove_first(authorities, (void**)&section) == SUCCESS)
+ {
+ if (unload_authority(conn, section, format))
+ {
+ unloaded++;
+ }
+ free(section);
+ }
+ authorities->destroy(authorities);
+
+ if (format & COMMAND_FORMAT_RAW)
+ {
+ return 0;
+ }
+ if (found == 0)
+ {
+ printf("no authorities found, %u unloaded\n", unloaded);
+ return 0;
+ }
+ if (loaded == found)
+ {
+ printf("successfully loaded %u authorities, %u unloaded\n",
+ loaded, unloaded);
+ return 0;
+ }
+ fprintf(stderr, "loaded %u of %u authorities, %u failed to load, "
+ "%u unloaded\n", loaded, found, found - loaded, unloaded);
+ return EINVAL;
+}
+
+static int load_authorities(vici_conn_t *conn)
+{
+ command_format_options_t format = COMMAND_FORMAT_NONE;
+ settings_t *cfg;
+ char *arg;
+ int ret;
+
+ while (TRUE)
+ {
+ switch (command_getopt(&arg))
+ {
+ case 'h':
+ return command_usage(NULL);
+ case 'P':
+ format |= COMMAND_FORMAT_PRETTY;
+ /* fall through to raw */
+ case 'r':
+ format |= COMMAND_FORMAT_RAW;
+ continue;
+ case EOF:
+ break;
+ default:
+ return command_usage("invalid --load-authorities option");
+ }
+ break;
+ }
+
+ cfg = settings_create(SWANCTL_CONF);
+ if (!cfg)
+ {
+ fprintf(stderr, "parsing '%s' failed\n", SWANCTL_CONF);
+ return EINVAL;
+ }
+
+ ret = load_authorities_cfg(conn, format, cfg);
+
+ cfg->destroy(cfg);
+
+ return ret;
+}
+
+/**
+ * Register the command.
+ */
+static void __attribute__ ((constructor))reg()
+{
+ command_register((command_t) {
+ load_authorities, 'b',
+ "load-authorities", "(re-)load authority configuration",
+ {"[--raw|--pretty]"},
+ {
+ {"help", 'h', 0, "show usage information"},
+ {"raw", 'r', 0, "dump raw response message"},
+ {"pretty", 'P', 0, "dump raw response message in pretty print"},
+ }
+ });
+}
diff --git a/src/swanctl/commands/load_authorities.h b/src/swanctl/commands/load_authorities.h
new file mode 100644
index 000000000..d4be214fb
--- /dev/null
+++ b/src/swanctl/commands/load_authorities.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2015 Andreas Stefffen
+ * HSR Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include "command.h"
+
+/**
+ * Load all certification authority definitions from configuration file
+ *
+ * @param conn vici connection to load to
+ * @param format output format
+ * @param cfg configuration to load from
+ */
+int load_authorities_cfg(vici_conn_t *conn, command_format_options_t format,
+ settings_t *cfg);
diff --git a/src/swanctl/swanctl.8.in b/src/swanctl/swanctl.8.in
index 543c10a67..cd033f91e 100644
--- a/src/swanctl/swanctl.8.in
+++ b/src/swanctl/swanctl.8.in
@@ -53,9 +53,15 @@ list currently active IKE_SAs
.B "\-P, \-\-list\-pols"
list currently installed policies
.TP
+.B "\-b, \-\-load\-authorities"
+(re\-)load certification authorities information
+.TP
.B "\-L, \-\-list\-conns"
list loaded configurations
.TP
+.B "\-B, \-\-list\-authorities"
+list loaded certification authorities information
+.TP
.B "\-x, \-\-list\-certs"
list stored certificates
.TP
@@ -63,7 +69,7 @@ list stored certificates
list loaded pool configurations
.TP
.B "\-q, \-\-load\-all"
-(re\-)load credentials, pools and connections
+(re\-)load credentials, pools, authorities and connections
.TP
.B "\-c, \-\-load\-conns"
(re\-)load connection configuration
diff --git a/src/swanctl/swanctl.conf b/src/swanctl/swanctl.conf
index faafecc44..c480ce174 100644
--- a/src/swanctl/swanctl.conf
+++ b/src/swanctl/swanctl.conf
@@ -180,6 +180,9 @@
# drop).
# mode = tunnel
+ # Whether to install IPsec policies or not.
+ # policies = yes
+
# Action to perform on DPD timeout (clear, trap or restart).
# dpd_action = clear
@@ -316,3 +319,25 @@
# }
+# Section defining attributes of certification authorities.
+# authorities {
+
+ # Section defining a certification authority with a unique name.
+ # <name> {
+
+ # CA certificate belonging to the certification authority.
+ # cacert =
+
+ # Comma-separated list of CRL distribution points
+ # crl_uris =
+
+ # Comma-separated list of OCSP URIs
+ # ocsp_uris =
+
+ # Defines the base URI for the Hash and URL feature supported by IKEv2.
+ # cert_uri_base =
+
+ # }
+
+# }
+
diff --git a/src/swanctl/swanctl.conf.5.main b/src/swanctl/swanctl.conf.5.main
index a770b28b1..6e3842d8a 100644
--- a/src/swanctl/swanctl.conf.5.main
+++ b/src/swanctl/swanctl.conf.5.main
@@ -726,6 +726,11 @@ are used to install shunt policies, which explicitly bypass
the defined traffic from IPsec processing, or drop it, respectively.
.TP
+.BR connections.<conn>.children.<child>.policies " [yes]"
+Whether to install IPsec policies or not. Disabling this can be useful in some
+scenarios e.g. MIPv6, where policies are not managed by the IKE daemon.
+
+.TP
.BR connections.<conn>.children.<child>.dpd_action " [clear]"
Action to perform for this CHILD_SA on DPD timeout. The default
.RI "" "clear" ""
@@ -1022,3 +1027,35 @@ corresponding attribute types. Alternatively,
can be a numerical
identifier, for which string attribute values are accepted as well.
+.TP
+.B authorities
+.br
+Section defining attributes of certification authorities.
+
+.TP
+.B authorities.<name>
+.br
+Section defining a certification authority with a unique name.
+
+.TP
+.BR authorities.<name>.cacert " []"
+The certificates may use a relative path from the
+.RB "" "swanctl" ""
+.RI "" "x509ca" ""
+directory, or an absolute path.
+
+.TP
+.BR authorities.<name>.crl_uris " []"
+Comma\-separated list of CRL distribution points (ldap, http, or file URI)
+
+.TP
+.BR authorities.<name>.ocsp_uris " []"
+Comma\-separated list of OCSP URIs
+
+.TP
+.BR authorities.<name>.cert_uri_base " []"
+Defines the base URI for the Hash and URL feature supported by IKEv2. Instead of
+exchanging complete certificates, IKEv2 allows one to send an URI that resolves
+to the DER encoded certificate. The certificate URIs are built by appending the
+SHA1 hash of the DER encoded certificates to this base URI.
+
diff --git a/src/swanctl/swanctl.opt b/src/swanctl/swanctl.opt
index b6ef17546..ef38d5d86 100644
--- a/src/swanctl/swanctl.opt
+++ b/src/swanctl/swanctl.opt
@@ -589,6 +589,12 @@ connections.<conn>.children.<child>.mode = tunnel
_pass_ and _drop_ are used to install shunt policies, which explicitly
bypass the defined traffic from IPsec processing, or drop it, respectively.
+connections.<conn>.children.<child>.policies = yes
+ Whether to install IPsec policies or not.
+
+ Whether to install IPsec policies or not. Disabling this can be useful in
+ some scenarios e.g. MIPv6, where policies are not managed by the IKE daemon.
+
connections.<conn>.children.<child>.dpd_action = clear
Action to perform on DPD timeout (_clear_, _trap_ or _restart_).
@@ -810,3 +816,35 @@ pools.<name>.<attr> =
subnets for the corresponding attribute types. Alternatively, **<attr>** can
be a numerical identifier, for which string attribute values are accepted
as well.
+
+authorities { # }
+ Section defining attributes of certification authorities.
+
+authorities.<name> { # }
+ Section defining a certification authority with a unique name.
+
+authorities.<name>.cacert =
+ CA certificate belonging to the certification authority.
+
+ The certificates may use a relative path from the **swanctl** _x509ca_
+ directory, or an absolute path.
+
+authorities.<name>.crl_uris =
+ Comma-separated list of CRL distribution points
+
+ Comma-separated list of CRL distribution points (ldap, http, or file URI)
+
+authorities.<name>.ocsp_uris =
+ Comma-separated list of OCSP URIs
+
+ Comma-separated list of OCSP URIs
+
+authorities.<name>.cert_uri_base =
+ Defines the base URI for the Hash and URL feature supported by IKEv2.
+
+ Defines the base URI for the Hash and URL feature supported by IKEv2.
+ Instead of exchanging complete certificates, IKEv2 allows one to send an
+ URI that resolves to the DER encoded certificate. The certificate URIs are
+ built by appending the SHA1 hash of the DER encoded certificates to this
+ base URI.
+